2014-07-12 27 views
1

我开始应该大致如下定义的超时时间内结束一个子进程:子进程长存

using (Process process = process.Start(startInfo)) 
{ 
    if (!process.WaitForExit(timeOutMilliSeconds)) 
    { 
     if (!process.HasExited()) 
     { 
      process.Kill(); 
     } 
    } 
} 

子进程是CPU密集型计算引擎(一SAT解算器)。我的主程序是用C#编写的,使用的是Visual Studio 2013Windows 7 64位

大多数情况下,上面的代码工作正常的进程超时终止已完成。但在约5%的案例中,process.Kill()没有明显的效果。儿童进程保持活跃。

我试图以较低的优先级启动子进程。在杀死它之前,我也试图暂停它。作为外部工具调用TASKKILL /F也并不总是有帮助。我注意到,所有SAT求解器都不会出现这个问题。我有管理权限,但不要以管理员身份运行主程序。

我该怎么做才能可靠地终止我的应用程序的子进程?

编辑:
除了超过其超时的预算,子进程的行为很正常,可以使用手动的Process Explorer(无管理员高程)被杀死。问题是如何确保在超时后没有进程继续运行。

解决方法:
我已经实现了使用VC++ 2013超时工具。我不是直接调用子进程,而是调用我的工具,然后调用子进程。该工具正在使用CreateProcess()TerminateProcess()来启动和停止子进程。 可能直接从C#程序中调用CreateProcess()TerminateProcess()而不产生额外的过程。
解决方法并不高雅,但它确实解决了我的问题。

+1

在Windows中,并不是所有的IO是撤销。如果进程有不可撤销的未完成的IO,它们可以进入一个不可驱动的僵尸状态。虽然这是非常罕见的。 – usr

+0

从'Kill'​​的文档:“Kill方法异步执行。调用Kill方法后,调用WaitForExit方法等待进程退出,或者检查HasExited属性以确定进程是否已退出。 –

+1

另外,尝试捕获来自Kill的异常,可能是因为您的应用也正在终止而导致异常被抛出,并且您没有看到异常。 –

回答

0

我制作了一个子进程管理库,其中父进程和子进程由于双向WCF管道而受到监视。如果子进程终止或父进程终止,则通知对方。 还有一个可用的调试器助手,它可以将VS调试器自动附加到启动的子进程。

也许你可以用它来控制你的孩子的过程。

项目选址:

http://www.crawler-lib.net/child-processes

的NuGet软件包:

https://www.nuget.org/packages/ChildProcesses https://www.nuget.org/packages/ChildProcesses.VisualStudioDebug/

+0

在我的应用程序中,子进程是我无法更改的外部第三方.exe进程。我只能使用普通的Windows机制来观察进程状态并发出kill命令。我可能不完全了解你的方法,但它不适用于我的情况。 –

+0

哦,我还以为孩子的过程也是用C#写的。事实上,我的方法对于第三方流程是不够的。 您是否尝试过终止您的过程而不杀死它?杀死一个进程可能会导致某些资源被阻塞,并且不可能一直存在。 –

+0

通过发送Ctrl-C终止控制台应用程序,并通过发送WM_CLOSE消息终止Windows应用程序。 http://stackoverflow.com/questions/283128/how-do-i-send-ctrlc-to-a-process-in-c http://stackoverflow.com/questions/5402158/using-sendmessage发送-WM-接近另一个进程 我只会杀死一个进程,如果这不起作用,并且进程真的“挂起” –