我试图从NSTask
内部发起NSOperation
。
这是一个very simple app我已经把它们放在一起来展示这个问题。单击该按钮时,NSOperation
排队。它设置NSRunLoop
,并调用一个调用NSTask
的方法。任务非常简单 - 只需启动/bin/sleep
两秒钟(足以在事情正常工作时轻松查看微调器)。
该应用程序的工作方式与广告相同,但如果您将TaskPerformer.m的第23行更改为autorelease
,(抱歉,我是新海报,因此我无法直接链接)或完全注释掉(因此泄漏NSTask
对象),NSOperation
的线程永远不会退出。它的主要runloop似乎阻止某事。
现在,这里的问题是双重的。首先,我不明白为什么我的线程会阻塞,而且,如果我打开这个应用程序的垃圾收集,同样的行为表现出来。因为我无法手动释放NSTask
,所以线程无论如何都会阻塞。
如果有人能告诉我发生了什么事,我会永远感激不尽!
答案 0 :(得分:4)
我在您发布的示例项目中看到了几个不同的问题。在TaskPerformer.m中,您有:
[task waitUntilExit];
[task launch];
{/ 1}}调用意味着在启动任务后调用,并且只是在任务完成之前阻塞并不执行任何操作。如果您只关心等待任务完成,而不是关于从中获取输出,那么您应该只需拨打waitUntilExit
后跟launch
,而不必费心去做运行循环。
如果您确实希望从任务中获取输出,那么您将需要获取其waitUntilExit
,默认情况下应该返回standardOutput
的实例。然后,您可以调用NSFileHandle
或readDataOfLength:
,两者都会在数据可用时阻止并返回流程中的数据。
因为这一切都将在后台线程中完成,所以这些方法可以阻塞,但是你不想在主线程上做同样的事情,因为这会锁定接口的用户,直到任务完成。如果您在主线程上执行此操作,则需要使用readDataToEndOfFile
的{{1}}和朋友。但是对于后台线程,使用NSFileHandle
时不一定非常必要。
答案 1 :(得分:1)
我弄清楚这里发生了什么。原来我对[runLoop run]
的调用正在设置循环并无限期地运行它。它永远不会落入while (!done)
循环。事实证明,在调用run
之后,NSRunLoop
将一直运行,直到它没有更多输入。在release
上调用NSTask
导致了这种情况,所以(非常偶然)我的runloop退出了。
解决方案是删除[runLoop run]
并依赖我自己的while
循环。希望这有助于其他人!