NSOperationQueue waitUntilAllOperationsAreFinished在后台工作时无法正常工作

时间:2013-03-29 13:15:58

标签: objective-c nsoperation nsoperationqueue

我正在处理的应用程序定期从应用程序服务器刷新它的本地数据缓存(10多个请求,每个请求需要相当长的时间)。我目前正在异步运行这些请求,以至于不阻止UI线程。由于这些请求确实需要一段时间来处理然后加载到核心数据中,因此我想利用beginBackgroundTaskWithExpirationHandler的{​​{1}}和相关操作行为。

在我将所有请求添加到操作队列后,我使用NSOperationQueue来阻止所有操作完成(这不在主线程上)。我在原型中看到的问题是,当我运行应用程序并立即将其背景(按下主页按钮)时,waitUntilAllOperationsAreFinished即使在所有操作完成后仍然被阻止...但是一旦我再次打开应用程序,处理程序完成。如果我运行应用程序并让它保持在前台,一切都很好。在我的实际应用程序中,这种行为似乎并不总是发生,但下面的示例代码似乎是:

waitUntilAllOperationsAreFinished

我做错了什么?

由于

2 个答案:

答案 0 :(得分:4)

您的示例代码不会在iPhone或模拟器上的iOS 6.1上的任何位置永久阻止。在[application endBackgroundTask:self.task];行放置一个断点,每次都会点击它。

您看到的行为是因为您在告诉应用程序结束后台任务后在后台进行日志记录。我不确定具体细节,但是当应用程序恢复到前台时,日志会以某种方式排队打印到控制台。可能是线程执行被挂起的情况。

如果您在致电NSLog(@"All done");之前移动endBackgroundTask:,则会看到记录的输出。

答案 1 :(得分:1)

使用您的示例代码,操作完成得很好。你挂在NSLog(@"All done :)");上了。您的队列仍然存在且没有待处理的操作,但您可能不再拥有活动的runloop,并且主线程在您和后台被阻止。由于您已完成待处理的后台操作,因此您将被阻止。当你恢复你的应用程序继续它停止的地方。如果你这样做:

    [[self queue] addOperationWithBlock:^{
        NSLog(@"All done :)");
    }];

行为应该更加明显。它正在做你正在告诉它的事情。

您排队了很多操作,并且您已调用waitUntilAllOperationsAreFinished。完成后,您将在后台被阻止。

在这组操作完成时,您似乎正在尝试执行某些操作。 NSOperation提供了依赖性和完成块的能力,允许您构建这种行为。您可以对操作进行分组,并设置在操作组完成时运行的完成块或操作。其中一些内容已在Concurrency Programming Guide

中介绍