有没有办法模拟
dispatch_apply()
块中的break语句?
例如,我看到处理枚举块的每个Cocoa API都有一个“停止”参数:
[array enumerateObjectsUsingBlock:^(id obj,NSUInteger i,BOOL *stop) { if ([obj isNotVeryNice]) { *stop = YES; // No more enumerating! } else { NSLog(@"%@ at %zu",obj,i); } }];
GCD有类似的东西吗?
解决方法
根据设计,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以指示枚举是否应该继续更合理.这样做会要求同步执行枚举块,即使在并发情况下也是如此,以便可以检查返回值.这样效率会大大降低.)