2010-08-27 4 views
10

Я недавно, как и несколько человек, обнаружил, что [ALAssetsLibrary enumerateGroupsWithTypes] любит запускать свои блоки в другом потоке. Какой позор, что Apple не документировала это :-)Синхронизация нити какао при использовании [ALAssetsLibrary enumerateGroupsWithTypes:]

В моем текущем обстоятельстве мне нужно дождаться завершения перечисления, прежде чем основной поток вернет какие-либо результаты. Мне явно нужна какая-то синхронизация потоков.

Я читал о NSLock & NSConditionLock, но ничего похожего не соответствует требованию «сигнал заблокированной нити, который завершил этот рабочий поток». Это кажется достаточно простой потребностью - может ли кто-нибудь указать мне в правильном направлении?

Ваш ключ & Боос, имеют большое значение, как всегда,

М.

ответ

2

Ответ использовать класс NSConditionLock Thusly ...

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

... 

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

Затем закрутить свою нить, или в моем случае вызов [ALAssetsLibrary enumerateGroupsWithTypes:]. Затем блок родительскую нить с этим ...

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

Когда вся работа выполняется в ребенка/работника нить, разблокированию родителя с этим ...

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

Не могли бы вы рассказать мне больше об этом решении? – MatterGoal

11

Рамки Безразлично» t запустите эти блоки в отдельном потоке. Он просто запускает их как дополнительные события в одном и том же цикле. Чтобы доказать это, попробуйте этот

[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"); 
    } 

Мой выход из этого был

main 
main 
main 

Это означает, что блок был вызывается в основном потоке. Это просто отдельное событие. Чтобы решить вашу проблему, вам нужно как можно скорее вернуть свое значение изнутри блока, когда вы достигнете последнего шага. Вы можете сказать, что это последний шаг, потому что ваш блок будет вызываться с nil для объекта group.

EDIT:, например, использовать этот блок

^(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

с использованием решения конца блока, хотя он не элегантный, но работает для меня пока. – user523234

2

Просто используйте это:

[library enumerateGroupsWithTypes:ALAssetsGroupAll 
          usingBlock:[^(ALAssetsGroup * group, BOOL * stop) 
{ 
    if(group == nil) 
    { 
     // this is end of enumeration 
    } 
} 
. 
. 
. 
Смежные вопросы