按照设计,dispatch_*()API 没有取消的概念。这样做的原因是因为几乎普遍正确的是,您的代码维护了何时停止或不停止的概念,因此,在 dispatch_*() API 中也支持这一点将是冗余的(并且,冗余会带来错误)。
因此,如果您想“提前停止”或取消调度队列中的待处理项目(无论它们如何入队),您可以通过与允许您取消的入队块共享一些状态来实现。
if (is_canceled()) return;
或者:
__block BOOL keepGoing = YES;
dispatch_*(someQueue, ^{
if (!keepGoing) return;
if (weAreDoneNow) keepGoing = NO;
}
请注意,两者enumerateObjectsUsingBlock:都enumerateObjectsWithOptions:usingBlock:支持取消,因为该 API 的角色不同。对枚举方法的调用是同步的,即使枚举块的实际执行可能是完全并发的,具体取决于选项。
因此,设置*stopFlag=YES告诉枚举停止。但是,它不保证在并发情况下会立即停止。事实上,枚举可能会在停止之前执行更多已经排队的块。
(有人可能会简单地认为,返回BOOL来指示枚举是否应该继续更合理。这样做需要同步执行枚举块,即使在并发情况下,也可以检查返回值。这个效率会大大降低。)