10

私は最近、[ALAssetsLibrary enumerateGroupsWithTypes]が別のスレッドでそのブロックを実行するのが好きであることを発見しました。Appleがそれを文書化しなかったのはなんと残念なことでしょう:-)

私の現在の状況では、メインスレッドが結果を返す前に、列挙が完了するのを待つ必要があります。ある種のスレッド同期が明らかに必要です。

NSLock と NSConditionLock について読んだことがありますが、「このワーカー スレッドが完了したことをブロックされたスレッドに通知する」という要件を満たすものはまだないようです。それは単純なニーズのように思えます-誰かが私を正しい方向に向けることができますか?

あなたの手がかりとブーイングは、いつものように大歓迎です。

M.

4

3 に答える 3

11

フレームワークは、これらのブロックを別のスレッドで実行しません。同じ実行ループで追加のイベントとしてそれらを実行するだけです。それを証明するには、これを試してください

    [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 で呼び出されるため、これが最後のステップであることがわかります。

編集:たとえば、このブロックを使用します

^(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)
    }
}
于 2011-07-14T22:32:03.803 に答える
2

これを使用するだけです:

[library enumerateGroupsWithTypes:ALAssetsGroupAll 
                           usingBlock:[^(ALAssetsGroup * group, BOOL * stop)
{
    if(group == nil)
    {
        // this is end of enumeration
    }
}
.
.
.
于 2014-03-02T12:34:57.457 に答える
2

答えは、このように NSConditionLock クラスを使用することです...

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];
于 2010-09-01T11:08:57.970 に答える