如何从GCD调度队列中删除排队的块?

Gök*_*ker 9 grand-central-dispatch ios

我正在尝试重新安排将处理更新操作的排队块.主要目标是以最少量(UI更新请求)更新UI对象(在线用户表...).(服务器有时会下大量的更新,是的!)

为简单起见,主要情况是;

  • dispatch_queue_t实例(将处理给定UI更新块的队列)是串行调度队列(专用调度队列)

  • 使用dispatch_after以t时间量调度操作(UI更新块)(而不是更新每个数据集更新,在t时间内收集更新请求并为它们执行单个UI更新)

  • 如果我们的数据集已更新,请检查是否已存在预定事件.如果是,则从dispatch_queue_t实例中取消计划.然后用t量的时间延迟重新调度相同的块.

也;

t是一小段时间间隔,可能不会被用户注意到(例如500毫秒).欢迎使用任何替代方法.

我背后的动机;

我通过Android的Handler应用相同的逻辑(post和removeCallbacks与Runnable实例的组合),我希望我能在iOS上实现相同的目标.

编辑:

由于@Sven建议使用NSOperationQueue更适合场景,因为它们支持取消每个NSOperation.我浏览文件并发现;

取消操作一旦添加到操作队列,操作对象就会被队列有效拥有,并且无法删除.使操作出列的唯一方法是取消它.您可以通过调用其cancel方法取消单个操作对象,也可以通过调用队列对象的cancelAllOperations方法取消队列中的所有操作对象.

只有在您确定不再需要操作时才应取消操作.发出取消命令会将操作对象置于"已取消"状态,从而阻止其运行.由于取消的操作仍被视为"已完成",因此依赖于它的对象会收到相应的KVO通知以清除该依赖关系.因此,更常见的是取消所有排队操作以响应某些重要事件,例如应用程序退出或用户特别请求取消,而不是有选择地取消操作.

das*_*das 14

这也可以通过GCD轻松完成,无需在这里找到NSOperationQueue的大锤子.

只需直接使用非重复的调度定时器源代码dispatch_after(这只是这种定时器源周围的便利包装器,它实际上不会将块排入队列,直到定时器关闭).

您可以使用重新计划挂起的计时器源执行dispatch_source_set_timer().

  • 那是不对的.NSOperationQueue不是GCD包装器,它是一个非常复杂的排队,依赖和优先级跟踪系统,与GCD完全分开实现.它在内部使用GCD进行某些同步(以及自旋锁和互斥锁)但是在客户端代码的执行方面,与GCD的唯一连接是NSOperationQueue在末尾对全局并发队列执行dispatch_async()以执行操作.准备好这样做.所有这些复杂性和灵活性都需要付出代价,NSOperationQueue比简单操作的GCD慢1000倍. (12认同)
  • lol @quellish - > https://www.linkedin.com/in/danielsteffen.我想这家伙知道他在说什么:) (8认同)
  • 对不起,没有"包装",除了排队的基本思想之外,NSOperationQueue没有与GCD相同的概念(甚至那不完全相同,并且没有在内部的GCD队列之上实现).这并不奇怪,因为NSOperationQueue API的设计比GCD早几年.至于性能差异,请随意自行测量......如果您认为文档在这些方面存在误导,请在bugreporter.apple.com上提交错误信息 (6认同)
  • NSOperation是围绕GCD的更高级别的并发包装器,它使用KVO和GCD原语来管理队列中的依赖性.QA1712,NSOperationQueue类引用以及并发编程指南都提到了这一点.对于简单的操作(即addOperationWithBlock),NSOperations不应该比GCD慢"1000s".如果是的话,你做错了什么. (5认同)

Sve*_*ven 6

您无法删除或以其他方式更改在调度队列中排队的操作.尝试使用更高级别NSOperationQueue而不是支持取消.