我有一个多线程程序,需要同时运行许多可执行文件并等待其结果。
我在[nstask waitUntilExit]
中使用NSOperationQueue
在非主线程上运行它(在主线程上运行NSTask
是完全不可能的。)
我的程序随机崩溃或遇到断言失败,崩溃堆栈总是指向由waitUntilExit
运行的runloop,它执行各种回调和处理程序,包括-IMHO错误-KVO和bindings updating the UI,这导致它们在非主线程上运行(它是probably the problem described by Mike Ash)
如何安全使用waitUntilExit
?
使用KVO和IB绑定来防止它们被处理时,waitUntilExit
本质上是不可用的问题,还是我需要做一些特殊的事情(除了在主线程上显式调度我的回调)运行waitUntilExit
的错误线程?
答案 0 :(得分: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);
答案 1 :(得分:0)
很难说没有你正在做什么的一般背景......
通常,您无法从非主线程更新接口。因此,如果您在非主线程和更新UI中观察到NSTasks的一些KVO通知,那么您就错了。
在这种情况下,您可以通过简单的
来解决问题-[NSObject performSelectorOnMainThread:];
或类似的想要更新UI。
但至于我更优雅的解决方案:
用maxConcurentOperationsCount = 1(所以FIFO队列)编写分离的NSOperationQueue并编写NSOperation的子类,它将执行NSTask并通过委托方法更新UI。这样,您将控制应用程序中执行任务的数量。 (或者你可以停止所有这些或其他)
但我认为,问题的高级解决方案是privileged helper tool。使用这种方法,您将获得两个主要好处:您的NSTask将在分离的过程中执行,并且您将拥有执行任务的root权限。
我希望我的答案能解决你的问题。