NSLock、ディスパッチバリア、NSOperationの依存関係などを使用して、さまざまなレベルの抽象化で目的の処理を実行する方法はいくつかあります。ただし、すでにGCDを使用しているため、dispatch_semaphore_*
関数は必要なことを簡単に実行します。
のようなもの(頭のてっぺんから、タイプミスがあるかもしれません:)
// this is the barrier one task will use to signal others that it's done.
dispatch_semaphore_t mySemaphore = dispatch_semaphore_create(0);
__block NSString *result = @"not done yet";
// adjust these to change which task "wins":
int hardTaskLength = 3;
int timeoutSeconds = 5;
// this is the first task:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// do something slow and difficult
sleep(hardTaskLength);
result = @"now I am done";
// then when we're done, let the world know:
dispatch_semaphore_signal(mySemaphore);
});
// and this is the second, dependent one:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeoutSeconds * NSEC_PER_SEC));
// wait for the first task to complete, or give up after a bit:
BOOL timedOut = dispatch_semaphore_wait(mySemaphore, timeout);
// now do stuff that wants the result of the first task
if (timedOut)
NSLog(@"Gave up waiting after %d seconds, result is: %@", timeoutSeconds, result);
else
NSLog(@"Processing finished; result is: %@", result);
// these can happen wherever is appropriate, after everything is done:
dispatch_release(mySemaphore);
mySemaphore = 0;
});
マニュアルセクション「GrandCentralDispatchreference」には、セマフォがどのように機能するかについての詳細があります。セマフォは本質的にスレッドセーフなカウンターです。カウンタがゼロでない限り、「信号」で1増加し、「待機」で1減少します。次に、「待機」が停止し、他の何かが再びカウンターを増やすまで待機してから、デクリメントして続行します。
ドキュメントから:「[dispatch semaphore_create]の値にゼロを渡すと、2つのスレッドが特定のイベントの完了を調整する必要がある場合に役立ちます。」それはまさにあなたがしていることです。
[編集して追加]:
ただし、質問の追加情報に基づくと、ディスパッチキューは、実行していることに対してやり過ぎのように見えます。とにかくすべてのUIKitはメインスレッドで発生する必要があるので、次のようにします。
- 5秒の開始時に、関心のあるプロパティにKVOを設定し、5秒のNSTimerを開始します。
- KVOリスナーで写真を撮り、タイマーをキャンセルします。
- タイマーハンドラー方式で、写真を撮り、KVO観測の登録を解除します。
- 最初に何か例外が発生し(キャンセルボタン?)、中止する必要がある場合は、両方ともKVOの登録を解除してタイマーをキャンセルします。
すべてがメインスレッドで発生するため、競合の心配はなく、タイマーはメインスレッドがブロックされないように処理します。