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

发布于 2024-09-16 12:58:01 字数 989 浏览 8 评论 0原文

问题

  • 我有一个名为 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。

我尝试过的

我尝试用 sleep 替换 runUntilDate,正如我所想,这意味着每个测试到达这里时都会永远暂停。

我的问题

是否有更好的方法来等待 NSOperationQueue 在主线程上完成?如果没有,我怎样才能让这段代码在 10.6 下运行?

The Problem

  • I have an NSOperationQueue called logEntryGeneratorQueue
  • I want to wait until all operations on the queue have completed

If I use:

[logEntryGeneratorQueue waitUntilAllOperationsAreFinished];

it works fine if the thread adding to the queue is in the background itself.

However, if I'm running this code via a unit test, it'll be running on the main thread. So I
came up with this "solution", which I really don't like:

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

This was always less than ideal, but has always worked fine on 10.5. However, now I've upgraded my project to using the 10.6 SDK, and this breaks.

On one test, it actually quit the test before it completed. I've no idea why - I assume it's something to do with the way NSOperationQueues work differently in 10.6 - they now use GCD.

What I've Tried

I've tried replacing the runUntilDate with sleep, which, as I thought, means every test pauses forever when it gets here.

My Question

Is there a better way to wait for an NSOperationQueue to finish on a main thread? If not, how can I get this code working under 10.6?

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

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

发布评论

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

评论(4

通知家属抬走 2024-09-23 12:58:01

解决方案

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

我认为答案是更改运行 NSOperationQueues 的位置。我不应该在主线程上运行处理核心数据的 NSOperationQueue。而且我想,出于性能原因,我真的不应该在主线程上运行这些密集的东西。

The Solution

I realised that my code was in an eternal loop because I was calling mergeChangesFromContextDidSaveNotification on the main thread whilst also waiting for the queue to finish on the main thread. And since the merge changes was called after waitUntilAllOperationsAreFinished, it never got executed.

I think the answer is to change where I run NSOperationQueues from. I shouldn't run an NSOperationQueue that deals with core data stuff on the main thread. And I shouldn't really be running this intensive stuff on the main thread for performance reasons anyway I guess.

久随 2024-09-23 12:58:01

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

I'd say that waitUntilAllOperationsAreFinished should work as expected on 10.6, no matter from what thread it's called. Since operation queues in 10.6 no longer use the run loop, there is no point in not blocking and having the loop run. Did you try to just call waitUntilAllOperationsAreFinished=

高速公鹿 2024-09-23 12:58:01

我同意 Max 的观点:-waitUntilAllOperationsAreFinished 应该有效。您的队列暂停了吗?

I agree with Max: -waitUntilAllOperationsAreFinished should work. Is your queue -suspended ?

貪欢 2024-09-23 12:58:01

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

IMHO you need to consider the possibility that waitUntilAllOperationsAreFinished may hang if one (or all) of its operations are progressing using main app thread as a carrier. Example: your nsoperation is not concurrent and uses glkview auto-update loop for animation and updating own state and your operation is only done (and operation is marked finished) only if main thread has a chance to work. But it can't as it is blocked in waiting for finishing these operations.

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