到目前为止,我已经浏览了 GCD 的文档,但似乎遗漏了 dispatch_cancel() ,我想用它来取消所有调度的 block 调用。 有没有办法实现dispatch_cancel()?
最佳答案
正如@HampusNilsson 所提到的,您无法在非垃圾收集环境(例如这个环境)中合理地取消任何正在进行的操作,因为它本质上会泄漏资源并使进程处于不确定状态。 NSOperationQueue
有一个取消 API,该 API 可用于实现飞行中操作的取消,前提是操作本身正在协作检查标志,然后清理并提前返回。这不是真正的硬中止。
至于取消入队但未开始的工作项,是的,NSOperationQueue
处理这个,但这需要一些额外的费用,NSOperationQueue
是更高级别的抽象。 GCD 的性能很大程度上取决于内部对无锁队列的使用。无锁队列将比基于锁的实现更快,但它需要进行某些权衡才能达到该速度。例如,我希望以无锁方式任意改变队列以删除已取消的操作要困难得多。我怀疑将公开的队列操作限制为“仅入队”,并使工作项本身不可变( block 和函数指针),为许多优化打开了大门,使 GCD 的开销如此之小,性能如此之好。
FWIW,在常见情况下,在现有 GCD API 之上实现可取消操作非常简单,因此需要此功能的任何人都可以很容易地自己完成(并且可能以更适合的方式)他们的特定需求而不是通用 API)。考虑以下函数——它将一个 block 排入队列并返回一个 block ,您稍后可以调用该 block 来取消入队操作:
dispatch_block_t dispatch_cancelable_async(dispatch_queue_t q, dispatch_block_t b)
{
__block uintptr_t isCancelled = 0;
dispatch_async(q, ^{
if (!isCancelled) b();
});
return [[^{ isCancelled = 1; } copy] autorelease];
}
这不是适用于所有情况的正确取消方法,但它是一个不错的第一近似值。
“使用最高级别的抽象来完成工作。”如果您想要取消,并且 NSOperationQueue
和 GCD 之间的开销差异不是重要因素,您应该只使用 NSOperationQueue
。有些人甚至会争辩说,在 Objective-C 中工作时,使用 NSOperationQueue
是更惯用的选择。除此之外,如图所示,在 GCD 之上为常见情况实现非中止取消是相当微不足道的。
基于所有这些,我怀疑构建 API 的取消在性能和复杂性方面并不值得权衡。
关于ios - 有没有办法实现dispatch_cancel()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18758583/