using(p = Process.Start(command))
这段代码可以编译通过,因为
Process
类实现了
IDisposable
接口,但是你实际上想要调用
Close
方法。
理论上说
Dispose
方法会自动调用
Close
方法,通过使用反射器查看CLR,我们可以看到它确实为我们执行了这个操作。目前为止还好。
再次使用反射器查看
Close
方法的功能 - 它释放底层的本地win32进程句柄并清除一些成员变量。这(释放外部资源)正是IDisposable模式应该做的事情。
但是我不确定这是否是你想在这里实现的。
释放底层句柄只是告诉Windows“我不再关心跟踪此其他进程”。它实际上没有导致其他进程退出,也没有导致您的进程等待。
如果您想要强制结束它们,您需要在进程上使用
p.Kill()
方法 - 但请注意,杀死进程从来都不是一个好主意,因为它们无法自我清理,可能会留下损坏的文件等等。
如果您想要等待它们自行退出,您可以使用
p.WaitForExit()
- 但是这只适用于一个进程一次等待。如果您想同时等待它们全部退出,这就有些棘手了。
通常,您会使用
WaitHandle.WaitAll
来实现此目的,但是由于无法从
System.Diagnostics.Process
中获取
WaitHandle
对象,因此无法完成此操作(说真的,微软在想什么?)。
您可以为每个进程启动一个线程,并在这些线程中调用`WaitForExit,但这也不是正确的方法。
相反,您必须使用P / Invoke访问本地win32
WaitForMultipleObjects
函数。
以下是一个示例(我已经测试过并且确实有效)。
[System.Runtime.InteropServices.DllImport( "kernel32.dll" )]
static extern uint WaitForMultipleObjects( uint nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds );
static void Main( string[] args )
{
var procs = new Process[] {
Process.Start( @"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 2'" ),
Process.Start( @"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 3'" ),
Process.Start( @"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 4'" ) };
// all started asynchronously in the background
var handles = procs.Select( p => p.Handle ).ToArray();
WaitForMultipleObjects( (uint)handles.Length, handles, true, uint.MaxValue ); // uint.maxvalue waits forever
}