ios - 有没有办法实现dispatch_cancel()?

标签 ios grand-central-dispatch

到目前为止,我已经浏览了 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/

相关文章:

ios - swift 4 : Navigation Controller unwanted looping

macos - 如何减慢 GCD 并发队列的任务?

ios - copypng 失败,退出代码为 1

ios - Swift:无法使用 'filter' 类型的参数列表调用 '((Any) throws -> Bool)'

iphone - 当GCD中的某个 block 执行失败时我们该如何处理?

ios - 我可以使用 RestKit 下载并解析大文件吗?

swift OSX : serially generating files using GCD

ios - 强制所有 UIKit 的东西在主线程中完成

ios - 发布音频 - Cocoa Xcode(内存管理)

android - 打开电子邮件中的链接以在应用程序而不是网站中进行确认