NSOperationQueue如何在引擎盖下取消?

时间:2014-05-30 01:45:50

标签: objective-c grand-central-dispatch nsoperation nsoperationqueue

根据Apple的文档,NSOperationQueue / NSOperation使用GCD。它提供了取消等功能,这在GCD中是不可用的。问题:如果GCD没有这种机制(或是否有机制),NSOperation如何实施取消?

2 个答案:

答案 0 :(得分:3)

根据NSOperationQueue Class Reference

  

排队操作在开始执行之前被取消。如果操作已在执行,则由该操作识别取消并停止正在执行的操作。

NSOperation Class Reference

  

取消操作不会立即强制它停止它   是在做。虽然尊重isCancelled返回的值是   期望所有操作,您的代码必须明确检查值   通过此方法返回并根据需要中止。默认   NSOperation的实施确实包括取消检查。   例如,如果在start方法之前取消操作   在调用时,start方法退出而不启动任务。

     

注意:在OS X v10.6中,取消方法的行为会有所不同   取决于操作当前是否在操作队列中。   对于未排队的操作,此方法将操作标记为已完成   立即生成适当的KVO通知。排队   操作,它只是将操作标记为准备执行并让   队列调用其start方法,随后退出并生成结果   从队列中清除操作。

     

您应始终支持任何自定义代码中的取消语义   你写。特别是,您的主要任务代码应该定期   检查isCancelled方法的值。如果方法永远返回   是的,您的操作对象应该清理并尽快退出   可能的。

据我了解,-[NSOperation cancel]只标记了一个标记,可能是isCancel。在-[NSOperation start]的顶部,它会检查标志,然后退出,如果它是真的 默认情况下,Apple仅支持取消当前未执行的操作。如果它在执行时被取消,则责任在-[NSOperation main]代码中,用户自己实现。

使用GCD,您可以通过将块包装在具有isCancel标志的类中来实现。在块的第一行,检查标志并退出,如果它是真的。

@interface CancelableBlock : NSObject
@property (copy) dispatch_block_t block;
@property (assign) BOOL isCancel;

- (dispatch_block_t)wrappedBlock;
@end

@implementation CancelableBlock 
- (dispatch_block_t)wrappedBlock {
  return ^{ if (self.isCancel) return; self.block(); };
}
@end

使用时

dispatch_async(queue, [myblock wrappedBlock]);

答案 1 :(得分:0)

近似答案:每个NSOperation存储一个被取消的位。当操作开始执行时,它会在执行任何操作之前检查已取消的位。