2012-06-01 8 views
6

ho 4 metodi, ogni metodo prende un secondo o due prima che il metodo restituisce, questi metodi restituiscono UIImage, ho bisogno di queste immagini per visualizzare il modo più veloce possibile.modo più veloce per eseguire più metodi tutti allo stesso tempo

-(NSMutableArray*)prepareImages{ 
    UIImage *imageToModifyUsingUIImageCategory; 

    NSMutableArray *imageArray = [[NSMutableArray alloc]initWithObjects: 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn1], 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn2], 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn3], 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn4],nil];  
    return imageArray; 
} 

alla fine del suddetto metodo, avrò 4 immagini da tale matrice. ogni metodo "doSomethingAndReturn" prende uno o due secondi, significa che il mio metodo prepareImages finirà esecuzione di circa 5 secondi. troppo a lungo eh?

La mia domanda è, quale potrebbe essere l'altro modo per realizzare tutto questo più velocemente? GCD è un'opzione per me? Come?

Qualsiasi aiuto sarebbe molto apprezzato. Grazie!

risposta

15

Dando per scontato che non si mente il caricamento delle immagini in sequenza in background (piuttosto che in parallelo), un semplice invio a una coda di sfondo per eseguire prepareImages farà il trucco:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
    NSArray *images = [self prepareImages]; 

    // now send the result back to the main thread so we can do 
    // UIKit stuff 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // set the images on your UIImageViews here... 
    }); 
}); 

Questo caricherà le immagini in una coda di sfondo a priorità bassa, quindi tornerà al thread principale una volta terminato.

Se si desidera mantenere questa priorità ancora più bassa, è possibile utilizzare lo DISPATCH_QUEUE_PRIORITY_BACKGROUND, sebbene questo sia disponibile solo in iOS 4.3 e versioni successive. Dovresti controllare il valore di ritorno da dispatch_get_global_queue in questo caso e se restituisce 0 puoi ricorrere a una delle altre priorità.

Se si desidera caricare ciascuna immagine in parallelo, è consigliabile convertire i metodi doSomethingAndReturn in sottoclassi NSOperation e utilizzare uno NSOperationQueue per eseguirli tutti. Ciò richiederebbe un po 'più di sforzo da implementare. Prestare attenzione anche all'utilizzo della memoria se si elaborano più immagini di grandi dimensioni contemporaneamente.

+0

grazie, stavo pensando di trasformare i miei metodi doSomethingAndReturn in NSOperation ma non ero sicuro di provarlo. ma proverò a fare gli sforzi da quando mi hai appena spinto :) btw, che ne dici di usare gcd con doSomethingAndReturn al posto di NSOperation? gcd è molto più elegante, credo, ma pensi che io possa realizzarlo con quello? Grazie! – janusbalatbat

+2

È possibile racchiudere ogni singola chiamata in doSomethingAndReturn nel proprio dispatch_async in modo che vengano eseguiti tutti in parallelo. Per aspettare che finiscano tutti, puoi creare un gruppo di spedizione. Vedere la documentazione qui: http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW25 –

+0

Grazie mille così tanto ... ho aiutato molto. –

1

Ho un'idea di come risolvere, ma non ancora testato. Sto disegnando la soluzione di diversi altri problemi che ho incontrato e risolto:

  • Inserire NSNull-NSMutableArray come segnaposto.
  • dispatch_async il lavoro pesante e sostituire la voce corrispondente NSMutableArray (utilizzare @synchronized parola chiave per bloccare il NSMutableArray)
  • Anche in dispatch async funzione, la spedizione di nuovo alla coda principale la funzione per aggiornare la vista.
+0

grazie per la risposta! cercherò di aggirare il problema non appena toccherò il mio mac. – janusbalatbat

1

si potrebbe usare un NSOperationQueue:

La classe NSOperationQueue regola l'esecuzione di un insieme di oggetti NSOperation. Dopo essere stato aggiunto a una coda, un'operazione rimane in quella coda fino a quando non viene cancellata in modo esplicito o termina l'esecuzione della sua attività. Le operazioni all'interno della coda (ma non ancora in esecuzione) sono esse stesse organizzate in base ai livelli di priorità e alle dipendenze degli oggetti tra operazioni e vengono eseguite di conseguenza. Un'applicazione può creare più code di operazioni e inviare operazioni a qualsiasi di esse.

example for a NSOperationQueue imeplementation

o un GCD Queue:

Grand Central Dispatch (GCD) code di spedizione sono un potente strumento per l'esecuzione di attività. le code di invio consentono di eseguire blocchi arbitrari di codice sia in modo asincrono o sincrono rispetto al chiamante. È possibile utilizzare le code di invio per eseguire quasi tutte le attività che si è utilizzato per eseguire su thread separati. Il vantaggio di code di spedizione è che sono più semplici da usare e molto più efficiente in esecuzione di tali compiti rispetto al codice filettato corrispondente.

example for a GCD Queue implementation

1

è possibile eseguire in tempo stesso su un altro core del processore per il fai che cercano:

NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; 
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; 
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; 
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; 

Se il processore quattro core ogni metodo sarà eseguire su un nucleo diverso.

0

Lo faccio solo come esercizio: utilizzare Q simultanea GCD per ogni DoSomethingAndReturn e utilizzare un q seriale per monitorare il numero di callback. Quando il numero di callback è uguale al numero di doSomethingAndReturn (s), restituire l'array prepareImages.

Ho creato il codice per testare il concetto.

-(NSString *)doSomethingAndReturn1 
{ 
    for (int i=0; i<30; i++) 
    { 
     NSLog(@"soSomethingAndReturn1 i: %i", i); 
    } 
    return @"soSomethingAndReturn1"; 
} 

-(NSString *)doSomethingAndReturn2 
{ 
    for (int i=0; i<10; i++) 
    { 
     NSLog(@"soSomethingAndReturn2 i: %i", i); 
    } 
    return @"soSomethingAndReturn2"; 
} 

-(NSString *)doSomethingAndReturn3 
{ 
    for (int i=0; i<20; i++) 
    { 
     NSLog(@"soSomethingAndReturn3 i: %i", i); 
    } 
    return @"soSomethingAndReturn3"; 
} 

-(void)addToArray:(NSString *)str 
{ 
    [asyncArray addObject:str]; 
    NSLog(@"asyncArray: %@", asyncArray); 
} 

- (IBAction)buttonMultitasksPressed:(id)sender 
{ 
    dispatch_queue_t serialdQueue; 
    serialdQueue = dispatch_queue_create("com.mydomain.testbed.multimethods", NULL); 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      [self addToArray:[self doSomethingAndReturn1]]; 
     }); 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      [self addToArray:[self doSomethingAndReturn2]]; 
     }); 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      [self addToArray:[self doSomethingAndReturn3]]; 
     }); 
     dispatch_sync(serialdQueue, ^{ 
      while (!([asyncArray count] == 3)) 
      { 
       NSLog(@"not there yet count: %i", [asyncArray count]); 
      } 
     }); 

    NSLog(@"end of dispatch_sync serialQueue"); 
// return asyncArray; 
} 

Modifica: 2 ° pensiero: il numero di serie non è necessario.

Problemi correlati