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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在主线程上安全地使用[NSTask waitUntilExit]?相关的知识,希望对你有一定的参考价值。

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

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

我的程序随机崩溃或遇到断言失败,崩溃堆栈总是指向由waitUntilExit运行的runloop,它执行各种回调和处理程序,包括-IMHO错误-KVO和bindings updating the UI,这导致它们在非主线程上运行(这是probably the problem described by Mike Ash

我怎样才能安全地使用waitUntilExit

这是waitUntilExit基本上无法使用的问题,还是我需要做一些特殊的事情(除了在主线程上显式调度我的回调),当使用KVO和IB绑定来防止它们在运行waitUntilExit的错误线程上处理?

答案

正如Mike Ash指出的那样,你无法在随机的runloop上调用waitUntilExit。它很方便,但不起作用。在计算“这实际上是否方便?”时,你必须包含“不起作用”。

但是,您可以在10.7+中使用terminationHandler。它不会泵送runloop,因此不应该产生这个问题。您可以使用这些行重新创建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);
另一答案

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

通常,您无法从非主线程更新接口。因此,如果您在非主线程和更新UI中观察到NSTasks的一些KVO通知,那么您就错了。

在这种情况下,你可以简单地解决问题

-[NSObject performSelectorOnMainThread:];

或者类似的想要更新UI。

但至于我更优雅的解决方案:

  1. 用maxConcurentOperationsCount = 1(所以FIFO队列)编写分离的NSOperationQueue并编写NSOperation的子类,它将执行NSTask并通过委托方法更新UI。这样,您将控制应用程序中执行任务的数量。 (或者你可以停止所有这些或其他)
  2. 但对于你的问题的高级解决方案,我认为将编写privileged helper tool。使用这种方法,您将获得两个主要好处:您的NSTask将在分离的进程中执行,并且您将拥有执行任务的root权限。

我希望我的答案涵盖你的问题。

以上是关于如何在主线程上安全地使用[NSTask waitUntilExit]?的主要内容,如果未能解决你的问题,请参考以下文章

GCD - 如何在主线程上等待在主队列上执行的异步回调

如何让工作线程在主 UI 线程上执行回调?

UIView setFrame 线程安全

挂钩事件 Outlook VSTO 在主线程上继续工作

使用改造向请求添加标头时如何避免在主线程上等待?

将 NSManagedObject(在主上下文中创建)从后台线程传递到主线程是不是安全?