2012-06-01 13 views
6

Ich habe 4 Methoden, jede Methode dauert eine Sekunde oder zwei vor der Methode zurück, diese Methoden zurück UIImage, ich brauche diese Bilder, um den schnellsten Weg anzuzeigen, den ich kann.schnellste Möglichkeit, mehrere Methoden alle gleichzeitig auszuführen

-(NSMutableArray*)prepareImages{ 
    UIImage *imageToModifyUsingUIImageCategory; 

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

Am Ende der obigen Methode, ich werde 4 Bilder von diesem Array haben. Jede "doSomethingAndReturn" -Methode dauert ein oder zwei Sekunden, dh meine prepareImages-Methode beendet die Ausführung ungefähr 5 Sekunden. zu lang, nicht wahr?

Meine FRAGE ist, was könnte der andere Weg sein, all diese schneller zu erreichen? Ist GCD eine Option für mich? Wie?

Jede Hilfe würde sehr geschätzt werden. Vielen Dank!

Antwort

15

Vorausgesetzt, dass Sie nichts dagegen haben die Bilder nacheinander im Hintergrund zu laden (statt parallel), ein einfacher Versand in einen Hintergrund Warteschlange prepareImages läuft den Trick:

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... 
    }); 
}); 

Dadurch werden die Bilder in eine Hintergrundwarteschlange mit niedriger Priorität geladen und nach Abschluss des Vorgangs an den Hauptthread zurückgegeben. Wenn Sie diese noch niedrigere Priorität beibehalten möchten, können Sie die DISPATCH_QUEUE_PRIORITY_BACKGROUND verwenden, obwohl dies nur in iOS 4.3 und höher verfügbar ist. Sie sollten in diesem Fall den Rückgabewert von dispatch_get_global_queue überprüfen und wenn er 0 zurückgibt, können Sie auf eine der anderen Prioritäten zurückgreifen.

Wenn Sie jedes Bild parallel laden möchten, sollten Sie wahrscheinlich Ihre doSomethingAndReturn Methoden in NSOperation Unterklassen und verwenden Sie eine NSOperationQueue, um sie alle auszuführen. Das würde ein wenig mehr Aufwand erfordern. Achten Sie auch auf die Speichernutzung, wenn Sie mehrere große Bilder gleichzeitig verarbeiten.

+0

danke, ich habe darüber nachgedacht, meine DoSomethingAndReturn-Methoden in NSOperation umzuwandeln, aber ich war nicht sicher, es zu versuchen. aber ich werde versuchen, die Bemühungen zu tun, da du mich einfach gedrängt hast :) Was ist nun, wenn du gcd mit doSomethingAndReturn anstelle von NSOperation verwendest? gcd ist viel eleganter, denke ich, aber denkst du, dass ich es damit erreichen kann? Vielen Dank! – janusbalatbat

+2

Sie können jeden einzelnen Aufruf für doSomethingAndReturn in seinem eigenen dispatch_async umbrechen, sodass alle gleichzeitig ausgeführt werden. Um darauf zu warten, dass alle fertig sind, können Sie eine Versandgruppe erstellen. Siehe die Dokumentation hier: http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW25 –

+0

Vielen Dank so viel ... Hat mir sehr geholfen. –

1

Ich habe eine Idee, wie zu lösen, aber noch nicht getestet. Ich zeichne die Lösung aus mehreren anderen Problemen, die ich festgestellt und gelöst:

  • Insert NSNull-NSMutableArray als Platzhalter.
  • dispatch_async die schwere Arbeit und ersetzen den entsprechenden Eintrag in NSMutableArray (Schlüsselwort verwendet @synchronized die NSMutableArray zu sperren)
  • Auch in dispatch async Funktion, Versand zurück zur Hauptwarteschlange der Funktion, die Ansicht zu aktualisieren.
+0

danke für die Antwort! Ich werde versuchen, das zu umgehen, sobald ich meinen Mac berühre. – janusbalatbat

1

Sie könnte verwenden NSOperationQueue:

Die NSOperationQueue Klasse regelt die Ausführung einer Reihe von NSOperation Objekten. Nach dem Hinzufügen zu einer Warteschlange verbleibt eine Operation in dieser Warteschlange, bis sie explizit abgebrochen wird oder die Ausführung der Task beendet wird. Operationen innerhalb der Warteschlange (aber noch nicht ausgeführt) sind selbst gemäß Prioritätsstufen und Abhängigkeiten zwischen Operationsobjekten organisiert und werden entsprechend ausgeführt. Eine Anwendung kann mehrere Vorgangswarteschlangen erstellen und Vorgänge an sie senden.

example for a NSOperationQueue imeplementation

oder ein GCD Queue:

Grand Central Dispatch (GCD) Dispatch-Warteschlangen sind ein mächtiges Werkzeug Aufgaben auszuführen. Mit Dispatch-Warteschlangen können Sie beliebige Code-Blöcke entweder asynchron oder synchron zum Aufrufer ausführen. Sie können Dispatch-Warteschlangen verwenden, um nahezu alle Aufgaben auszuführen, die Sie für separate Threads ausgeführt haben. Der Vorteil von Dispatch-Warteschlangen besteht darin, dass sie einfacher zu verwenden und effizienter auszuführen sind als der entsprechende Thread-Code.

example for a GCD Queue implementation

1

Sie können in der gleichen Zeit auf einem anderen Kern Ihres Prozessors für do ausführen, die versuchen:

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]; 

Wenn Ihr Prozessor mit vier Kernen jede Methode hat, wird auf einem anderen Kern auszuführen.

0

Ich mache es nur als Übung: Verwenden Sie GCD gleichzeitige Q für jedes doSomethingAndReturn und verwenden Sie eine serielle q, um die Anzahl der Rückrufe zu überwachen. Wenn die Anzahl der Rückrufe gleich der Anzahl von doSomethingAndReturn (s) ist, geben Sie das prepareImages-Array zurück.

Ich habe den Code erstellt, um das Konzept zu testen.

-(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; 
} 

Edit: 2. Gedanke: Die serielle ist nicht notwendig.

Verwandte Themen