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

问题描述 投票:4回答:2

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

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

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

我怎样才能安全地使用waitUntilExit

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

multithreading cocoa nstask
2个回答
4
投票

正如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);

0
投票

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

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

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

-[NSObject performSelectorOnMainThread:];

或者类似的想要更新UI。

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.