NSOperation和NSOperationQueue取消操作

4

我在一个 NSOperationQueue 实例中排队一些自定义的 NSOperation 实例,但是遇到了一些奇怪的问题:

当我调用 [myOperation cancel] 或者 [myOperationQueue cancelAllOperations] 方法时,我的自定义 NSOperation 子类实例的 cancel 布尔值的 isCancelled 属性仍然没有改变。

我试图在应用程序委托的 applicationWillResignActive 方法被调用时取消这些操作。

我的 NSOperation 子类实现如下:

  • 自定义初始化方法
  • 实现了 main 方法

我有一个单例持有我的 NSOperation 子类实例和 NSOperationQueue 实例的强引用。

在该单例的一个方法中,我执行以下操作:

myNSOperationQueueInstance = [[NSOperationQueue alloc] init];
myCustomOperation_1 = [MyCustomOperationClass alloc] customInit];
myCustomOperation_2 = [MyCustomOperationClass alloc] customInit];

[myNSOperationQueueInstance addOperations:@[myCustomOperation_1,myCustomOperation_2] waitUntilFinished:NO];

直到现在,一切都按预期进行,自定义操作开始执行。
然而,当我从 applicationWillResignActive 调用我的单例的另一个方法来取消我的自定义操作,使用 [myCustomOperation cancel][myNSOperationQueueInstance cancelAllOperations] 时,isCancelled 布尔值保持不变(我会定期检查自定义操作的执行循环中的 isCancelled)。
另一个有趣的事情是,在应该取消操作的同一个方法中,如果我使用 NSLog 检查 isCancelled、isExecuting、isAsynchronous 这些布尔值都设置为 NO,但 isFinished 布尔值却设置为 YES,即使操作正在执行。
此外,如果我尝试使用 operations 属性查看我的 NSOperationQueue 中排队的操作,则该数组为空。
如果我覆盖 NSOperation 子类的 cancel 属性及其 setter 方法,它就像预期的那样工作。
我还从系统请求了一个长时间运行的后台任务,这也很有效,因此问题不是由于操作无法在应用变为非活动状态之前被取消。
我错过了什么?为什么 isCancelled getter 不改变,为什么 NSOperationQueueoperations 数组属性为空,尽管我添加了操作并且在查询数组时它们正在执行,为什么 isFinished 布尔值设置为 YES,而操作正在执行?

不是因为它们不是并发的,我不想手动启动它们。我想允许NSOperationQueue启动它们。我也没有覆盖子类的“start”方法。 - Razvan
1
你的 -main 是同步的吗?它在操作完全完成之前不会返回吗? - Ken Thomases
1
所以你的操作通常不会在完全完成之前返回?你能澄清一下吗?你的代码说 [myNSOperationQueueInstance addOperations:@[myCustomOperation_1,myCustomOperation_2] waitUntilFinished:NO]; - lead_the_zeppelin
1
你能否发布你的 [MyCustomOperationClass customInit] 代码? - lead_the_zeppelin
@lead_the_zeppelin 我正在尝试使用waitUntilFinished,看看它是否有影响,并将最后一次更改复制到这里:)。似乎并不重要,因为isFinished布尔值无论如何都是YES - Razvan
显示剩余2条评论
1个回答

2
感谢 @KenThomases@lead_the_zeppelin(请参见 OP 中的评论),我能够找出代码中的缺陷:
由于我创建了自定义的 NSOperation 子类来导入数据到 Core Data 模型,我的错误在于执行导入的代���是从子类的 -main 方法中调用的,并且嵌套在异步的 performBlock 方法的块回调作用域内,该方法是我用来管理导入执行的 ManagedObjectContext
所以发生的情况是,-main 内部的代码在另一个线程中异步运行,而不是在操作实例中运行,因此操作实例报告其完成执行。在我的情况下,为了解决这个问题,我将 performBlock: 更改为 performBlockAndWait:结论:如果您遇到与我相同的问题,请检查自定义 NSOperation 子类的 -main 实例方法中运行的代码是否在异步运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接