2010-08-27 5 views
10

Ich habe kürzlich, wie ein paar Leute, entdeckt, dass [ALAssetsLibrary enumerateGroupsWithTypes] gerne seine Blöcke auf einem anderen Thread ausführen. Was für eine Schande, dass Apple das nicht dokumentiert hat :-)Cocoa-Thread-Synchronisation bei der Verwendung von [ALAsetsLibrary enumerateGroupsWithTypes:]

In meinem aktuellen Umstand muss ich warten, bis die Aufzählung abgeschlossen ist, bevor der Hauptthread Ergebnisse zurückgibt. Ich brauche eindeutig eine Art Thread-Synchronisation.

Ich habe über NSLock & NSConditionLock gelesen, aber noch nichts scheint die Anforderung von "Signal ein blockierter Thread, dass dieser Arbeiter Thread abgeschlossen hat" zu passen. Es scheint ein einfaches Bedürfnis zu sein - kann mir jemand in die richtige Richtung zeigen?

Ihr Hinweis & Boos, sind herzlich eingeladen, wie immer,

M.

Antwort

2

Die Antwort ist thusly die NSConditionLock Klasse zu verwenden ...

typedef enum { 
    completed = 0, 
    running = 1 
} threadState; 

... 

NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:running]; 

Dann Thread ausgliedern, oder in meinem Fall ein Aufruf von [ALAsetsLibrary enumerateGroupsWithTypes:]. Dann blockieren die Muttergewinde mit diesem ...

// Await completion of the worker threads 
[lock lockWhenCondition:completed]; 
[lock unlockWithCondition:completed]; 

Wenn alle Arbeiten im Kind getan wird/Arbeiter Thread entsperren die Eltern mit diesem ...

// Signal the waiting thread 
[lock lockWhenCondition:running]; 
[lock unlockWithCondition:completed]; 
+1

Könnten Sie mir sagen, mehr über diese Lösung? – MatterGoal

11

Der Rahmen doesn‘ t führen Sie diese Blöcke in einem separaten Thread aus. Es führt sie nur als zusätzliche Ereignisse in derselben Laufschleife aus. Um das zu beweisen, versuchen Sie diese

[library enumerateGroupsWithTypes:ALAssetsGroupAll 
          usingBlock:[^(ALAssetsGroup * group, BOOL * stop) 
          { 
           if([NSThread isMainThread]) 
           { 
            NSLog(@"main"); 
           } 
           else 
           { 
           NSLog(@"non-main"); 
           } 
          } copy] 
      failureBlock:^(NSError * err) 
          {NSLog(@"Erorr: %@", [err localizedDescription]);}]; 
    [library release]; 
    if([NSThread isMainThread]) 
    { 
     NSLog(@"main"); 
    } 
    else 
    { 
     NSLog(@"non-main"); 
    } 

Meine Ausgabe von diesem war

main 
main 
main 

Was bedeutet, dass der Block im Hauptthread genannt wurde. Es ist nur eine separate Veranstaltung. Um Ihr Problem zu lösen, müssen Sie nur Ihren Wert irgendwie aus dem Block zurückgeben, wenn Sie den letzten Schritt erreichen. Sie können sagen, dass es der letzte Schritt ist, weil Ihr Block mit nil für das Gruppenobjekt aufgerufen wird.

EDIT: zum Beispiel verwenden diesen Block

^(ALAssetsGroup * group, BOOL * stop) 
{ 
    if(group == nil) 
    { 
     // we've enumerated all the groups 
     // do something to return a value somehow (maybe send a selector to a delegate) 
    } 
} 
+0

mit End-of-Block-Lösung, obwohl ist nicht ein elegantes, aber funktioniert für mich für jetzt. – user523234

2

einfach verwenden:

[library enumerateGroupsWithTypes:ALAssetsGroupAll 
          usingBlock:[^(ALAssetsGroup * group, BOOL * stop) 
{ 
    if(group == nil) 
    { 
     // this is end of enumeration 
    } 
} 
. 
. 
. 
Verwandte Themen