設計上、dispatch_*()
API にはキャンセルの概念がありません。この理由は、コードが停止するタイミングと停止しないタイミングの概念を維持していることがほぼ普遍的に真実であり、したがって、dispatch_*() API で冗長になることもサポートするためです (冗長性にはエラーが伴います)。
したがって、ディスパッチ キュー内の保留中のアイテムを「早期に停止」したい場合 (それらがキューに入れられた方法に関係なく)、取り消すことができる状態の一部をキューに入れられたブロックと共有することによって行います。
if (is_canceled()) return;
または:
__block BOOL keepGoing = YES;
dispatch_*(someQueue, ^{
if (!keepGoing) return;
if (weAreDoneNow) keepGoing = NO;
}
enumerateObjectsUsingBlock:
その API の役割が異なるため、両方とenumerateObjectsWithOptions:usingBlock:
両方がキャンセルをサポートしていることに注意してください。オプションによっては、列挙ブロックの実際の実行が完全に同時実行される場合でも、列挙メソッドの呼び出しは同期的です。
したがって、を設定する*stopFlag=YES
と、列挙が停止するように指示されます。ただし、同時実行の場合にすぐに停止することを保証するものではありません。実際、列挙は、停止する前に、すでにキューに入れられたブロックをさらにいくつか実行する場合があります。
(列挙を続行するかどうかを示すために戻る方がより合理的であると簡単に考えるかもしれませんBOOL
。これを行うには、戻り値をチェックできるように、並列の場合でも、列挙ブロックを同期的に実行する必要がありました。この効率が大幅に悪くなります。)