如何在主线程之外安全地使用 [NSTask waitUntilExit]?

How to safely use [NSTask waitUntilExit] off the main thread?

我有一个多线程程序需要同时 运行 许多可执行文件并等待它们的结果。

我在 NSOperationQueue 中使用 [nstask waitUntilExit],运行 在非主线程上使用它(运行宁 NSTask 在主线程上完全不可能的)。

我的程序随机崩溃或 运行s 断言失败,并且崩溃堆栈始终指向 运行循环 运行 by waitUntilExit,它执行各种回调和处理程序,包括——恕我直言——KVO 和 , which causes them to run on non-main thread (It's probably the problem described by Mike Ash)

如何安全使用waitUntilExit

这是 waitUntilExit 本质上不可用的问题,还是在使用 KVO 和 IB 绑定时我需要做一些特殊的事情(除了在主线程上明确安排我的回调)以防止它们被使用在错误的线程上处理 运行ning waitUntilExit?

如果没有你在做什么的一般背景,很难说...

一般来说你不能从非主线程更新界面。因此,如果您在非主线程中观察到 NSTasks 的一些 KVO 通知并更新 UI 那么您就错了。

在这种情况下,您可以通过简单的方法解决问题

-[NSObject performSelectorOnMainThread:];

或类似的当你想更新 UI.

但对我来说更优雅的解决方案:

  1. 用 maxConcurentOperationsCount = 1 编写分离的 NSOperationQueue(因此 FIFO 队列)并编写 NSOperation 的子类,它将执行 NSTask 并通过委托方法更新 UI。通过这种方式,您将控制应用程序中执行任务的数量。 (或者你可以停止所有这些,否则)

  2. 但是我认为针对您的问题的高级解决方案是编写 privileged helper tool。使用这种方法,您将获得 2 个主要好处:您的 NSTask 将在单独的进程中执行,并且您将拥有执行任务的 root 权限。

希望我的回答能解决您的问题。

正如 Mike Ash 指出的那样,您不能在随机运行循环中调用 waitUntilExit。这很方便,但它不起作用。您必须在 "is this actually convenient?"

的计算中包含 "doesn't work"

但是,您可以在 10.7+ 中使用 terminationHandler。它不抽运行循环,所以不应该产生这个问题。您可以使用以下内容重新创建 waitUntilExit(未经测试;可能无法编译):

dispatch_group group = dispatch_group_create();
dispatch_group_enter(group);
task.terminationHandler = ^{ dispatch_group_leave(group); };
[task launch];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

// If not using ARC:
dispatch_release(group);