我如何等待NSOperationQueue完成单元测试?

时间:2010-09-01 15:39:23

标签: objective-c cocoa osx-snow-leopard nsoperation nsoperationqueue

问题

  • 我有一个名为logEntryGeneratorQueue
  • 的NSOperationQueue
  • 我想等到队列中的所有操作都完成

如果我使用:

[logEntryGeneratorQueue waitUntilAllOperationsAreFinished];

如果添加到队列的线程在后台本身,它可以正常工作。

但是,如果我通过单元测试运行此代码,它将在主线程上运行。所以我 想出了这个“解决方案”,我真的不喜欢这个:

if ([NSThread isMainThread]) {
    while ([[logEntryGeneratorQueue operations] count] > 0) {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
    }
} else {
    [logEntryGeneratorQueue waitUntilAllOperationsAreFinished];
}

这总是不太理想,但在10.5上一直很好。但是,现在我已经将我的项目升级到使用10.6 SDK了,这就打破了。

在一次测试中,它实际上在测试完成之前退出测试。我不知道为什么 - 我认为它与NSOperationQueues在10.6中的工作方式有关 - 他们现在使用GCD。

我尝试过什么

我已经尝试用run替换runUntilDate,正如我所想的那样,这意味着每次测试都会在到达时暂停。

我的问题

有没有更好的方法等待NSOperationQueue在主线程上完成?如果没有,我怎么能让这个代码在10.6下工作?

4 个答案:

答案 0 :(得分:2)

解决方案

我意识到我的代码是在一个永恒的循环中,因为我在主线程上调用mergeChangesFromContextDidSaveNotification同时还在等待队列在主线程上完成。由于合并更改是在waitUntilAllOperationsAreFinished之后调用的,因此它从未执行过。

我认为答案是改变我从哪里运行NSOperationQueues。我不应该运行一个NSOperationQueue来处理主线程上的核心数据。出于性能原因,我不应该在主线程上运行这些密集的东西,无论如何我想。

答案 1 :(得分:1)

我会说waitUntilAllOperationsAreFinished应该在10.6上按预期工作,无论从哪个线程调用它。由于10.6中的操作队列不再使用运行循环,因此没有阻塞和循环运行的意义。您是否尝试拨打waitUntilAllOperationsAreFinished =

答案 2 :(得分:1)

我同意Max:-waitUntilAllOperationsAreFinished应该有效。你的队列是否已暂停?

答案 3 :(得分:0)

恕我直言,如果一个(或所有)操作正在使用主应用程序线程作为载体进行,则需要考虑waitUntilAllOperationsAreFinished可能会挂起的可能性。示例:您的nsoperation不是并发的,并且使用glkview自动更新循环来动画和更新自己的状态,并且只有在主线程有机会工作时才会执行操作(并且操作已标记为已完成)。但它无法阻止等待完成这些操作。