有其他人在 10.6 中看到或听说过 NSTask 的任何问题吗?
该代码昨天运行良好,今天无法正常运行。
NSTask *task = [converter task];
[task waitUntilExit];
NSLog(@"Task did complete");
该任务完成了它应该做的事情(我检查了输出,它很好),但程序将无限期地等待该waitUntilExit
方法。我有一些使用类似代码的单元测试,它们以前都通过了,但截至昨天,它们不再工作。
有其他人在 10.6 中看到或听说过 NSTask 的任何问题吗?
该代码昨天运行良好,今天无法正常运行。
NSTask *task = [converter task];
[task waitUntilExit];
NSLog(@"Task did complete");
该任务完成了它应该做的事情(我检查了输出,它很好),但程序将无限期地等待该waitUntilExit
方法。我有一些使用类似代码的单元测试,它们以前都通过了,但截至昨天,它们不再工作。
您需要添加以下魔术线:
[task setStandardInput:[NSPipe pipe]];
(1) 你是否以任何方式处理任务的输出?如果是这样,如果您不沿途读取和处理数据,输出的缓冲可能会阻塞。
(2) 您的任务在终止之前是否在标准输入上等待 EOL?如果是这样,您将需要获取标准输入并明确关闭它。
正如彼得所说,检查 ps 以查看您的任务是否仍在运行。如果是,sample
请对它进行采样以找出它在做什么。
可能 - 我注意到我在 10.6 上的一些代码有问题,这听起来很像你的问题。
我需要以完全异步的方式获取一些网络信息(主要是关于 BGP 和 AS 的东西)。对我来说理想的解决方案是将特殊的 DNS TXT 记录请求发送到可公开访问的 DNS 服务器,但 Cocoa/Core Foundation 不提供 API 来执行这些奇怪的 DNS 请求。另一种方法是使用shell% whois -h IP 'SPECIAL REQUEST'
并从输出中解析出相关信息。这是我可以在几个小时内启动并运行的东西,然后再回来并提出一个真正的解决方案。非常 hacky,但比 1) 找到合适的异步 DNS 库和 2) 加快其 API 的速度并可能为其编写包装器要快得多。
因此,我创建了一个分叉后台线程的类,然后NSTask
启动whois
请求。后台线程位于一个NSRunLoop
循环中以处理结果,但每隔约 1/10 秒检查一次以查看是否NSTask
因某种原因死亡,或者 if[NSThread isCanceled]
等。它还注册NSApplicationWillTerminateNotification
通知,以便它可以进行适当的清理,如果应用程序正在退出。
好吧,从 10.6 开始……我不能再“快速”退出了。在 10.5 上,一切都是玻璃般光滑的,应用程序会立即退出,至少在感知上是这样。在 10.6 下,退出会导致应用“挂起”。调试表明一切都在试图清理挥之不去whois NSTask
的 s。由于我以这种方式获得的所有信息都不是应用程序功能的关键(这是额外的,很高兴知道某种信息),我只是有点下注并停止尝试将信息作为权宜之计解决方案。
调试问题的快速通过表明主应用程序在尝试获取实例时被阻止NSLock
。有趣的是,如果我不理会它,应用程序最终会正常退出——从 10-20 秒到几分钟不等。在 10.5 和 10.6 之间发生了一些变化,导致[NSLock lock] ... [NSLock unlock]
块内的代码“花费很长时间”。不过,我还没有追查到发生这种情况的地方(还不是优先事项)....但是其中一件事是终止后台NSTask
,如果它仍在运行并“等待它完成”,然后才能安全地摆脱它像它的东西NSPipe
。
DUP:这可能是一个骗人的答案……我的第一个似乎已经消失了?
检查 ps、top 或 Activity Monitor。确保您的进程已退出。
不确定这是否有帮助,但您可以尝试在单独的线程上等待:
[NSThread detachNewThreadSelector: @selector(foo) toTarget: self withObject: task];
...
- (void) foo: (NSTask *) task {
[task launch];
[task waitUntilExit];
...
我遇到了一个问题,任务完成后我没有收到 NSNotification,这解决了它。显然在 10.6 下的 NSTask 实现中存在一些错误......