主线程无限期挂起,等待NSOperationQueue操作取消[仅限设备!]

时间:2009-12-15 23:24:51

标签: iphone multithreading nsoperation

我的主线程上有一个NSOperationQueue,它运行一组NSOperations(最大并发设置为1),我希望能够随时取消。当我按下按钮时,我告诉队列取消所有操作并等到完成。这应该挂起主线程,直到操作队列为空,但是它无限期挂起我的主线程。

这是我用来阻止它的代码:

...
[myQueue cancelAllOperations];
[myQueue waitUntilAllOperationsAreFinished];
return YES; // This line never gets called

注意:我需要使用waitUntilAllOperationsAreFinished,因为进一步的流程要求队列为空。

奇怪的是这只发生在设备上。在模拟器中运行时,它按预期工作。

我已经看过断点,我可以按照当前运行的操作直到完成。它检测[self isCancelled],停止正在进行的操作并将其拉到main方法的末尾。我可以看到操作中没有任何东西导致它挂起,并且通过取消所有操作,其他任何操作都不应该启动,队列应该完成。我通过添加断点进行检查,其他操作都没有启动。

为什么会这样?

3 个答案:

答案 0 :(得分:8)

在您的任何操作(或任何其他线程)中,您使用的是-performSelectorOnMainThread:withObject:waitUntilDone:吗? -waitUntilAllOperationsAreFinished将阻止它被调用的任何线程,直到所有操作完成。可能的情况是,如果你在应用程序终止时调用它,那么该线程将成为主线程。如果主线程被阻止,并且其中一个操作使用-performSelectorOnMainThread:withObject:waitUntilDone:,则您的应用程序将冻结,因为操作永远不会完成。

我之前发生过这件事。不幸的是,它很难解决。

答案 1 :(得分:5)

你永远不应该阻止主线程。它会处理所有UI更新,因为您已经注意到您设法创建了死锁。

相反,尝试创建一个方法,如:

- (void) notifyOnFinish
{
   [myQueue waitUntilAllOperationsAreFinished];
   [self performSelectorOnMainThread:(queueEmpty) withObject:nil waitUntilDone:NO];
}

然后,您现在拥有代码,请致电:

[myQueue cancelAllOperations];
[self performSelectorInBackground:@selector(notifyOnFinish) withObject:nil];

在queueEmpty方法中,只需在清空队列时执行任何操作。

基本上,只需创建一个后台线程来阻止而不是主线程。

答案 2 :(得分:0)

也许waitUntilAllOperationsArefFinished正在导致阻塞...也许操作全部取消并在调用waitUntilAllOperationsArefFinished之前完成,然后队列处于挂起状态,等待已完成的操作完成...?

我不知道这个事实,但也许不要打电话给waitUntilAllOperationsArefFinished