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

发布于 2024-08-14 09:09:27 字数 639 浏览 2 评论 0原文

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

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

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

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

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

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

为什么会发生这种情况?

I have an NSOperationQueue on my main thread running a set of NSOperations (max concurrent set to 1) that I want to be able to cancel at any time. When I press a button I tell the queue to cancel all operations and wait until finished. This should hang the main thread until the operation queue is empty, however it is hanging my main thread indefinitely.

Here's the code I use to stop it:

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

Note: I need to use waitUntilAllOperationsAreFinished as further processes require that the queue be empty.

The strange thing is this is only occurring on the device. When running in the simulator it works as expected.

I have watched breakpoints and I can follow the currently running operation until it finishes. It detects [self isCancelled], stops what it's doing and zips through to the end of the main method. I can see that nothing in the operation is causing it to hang, and by cancelling all operations, none of the other operations should start, and the queue should finish. I have checked by adding breakpoints and none of the other operations start.

Why is this happening?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

走野 2024-08-21 09:09:27

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

我以前也经历过这样的事情。不幸的是,解决这个问题非常困难。

In any of your operations (or in any other thread), are you using -performSelectorOnMainThread:withObject:waitUntilDone:? -waitUntilAllOperationsAreFinished will block whatever thread it's called on until all operations are complete. Odds are, if you're calling this as the application is terminating, that thread would be the main thread. If the main thread is blocked, and one of the operations uses -performSelectorOnMainThread:withObject:waitUntilDone:, your application will freeze because the operation will never complete.

I've had this exact thing happen to me before. Unfortunately, it's pretty difficult to work around.

澉约 2024-08-21 09:09:27

你永远不应该阻塞主线程。它一方面处理你所有的 UI 更新,另一方面,正如你所注意到的,你设法造成了死锁。

相反,尝试创建如下方法:

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

然后,在您现在拥有代码的地方,调用:

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

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

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

You should never, ever block the main thread. It handles all your UI updates for one thing, for another as you have noted you managed to create a deadlock.

Instead, try creating a method like:

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

Then where you have your code now, call:

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

And in a queueEmpty method you just do whatever you want to do when the queue is emptied.

Basically, just create a background thread to block instead of the main thread.

仙女 2024-08-21 09:09:27

也许 waitUntilAllOperationsArefFinished 导致了阻塞...也许操作在调用 waitUntilAllOperationsArefFinished 之前全部取消并完成,然后队列挂起,等待已经执行的操作完结了……?

我确实不知道这一点,但也许尝试不调用 waitUntilAllOperationsArefFinished

Perhaps the waitUntilAllOperationsArefFinished is causing the block... Maybe the operations all cancel and finish before the call to waitUntilAllOperationsArefFinished and then the queue is sat hanging, waiting for operations that are already finished to finish...?

I don't know this for a fact, but maybe try not calling waitUntilAllOperationsArefFinished.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文