using(p = Process.Start(command))
这将编译,因为Process
类实现了IDisposable
,但是您实际上想要调用该Close
方法。
从逻辑上讲,该Dispose
方法会Close
为您调用,并且通过使用反射器深入研究 CLR,我们可以看到它实际上为我们执行了此操作。到现在为止还挺好。
再次使用反射器,我查看了该Close
方法的作用——它释放了底层的本机 win32 进程句柄,并清除了一些成员变量。这(释放外部资源)正是IDisposable 模式应该做的。
但是我不确定这是否是您想要在这里实现的目标。
释放底层句柄只是对 Windows 说“我不再对跟踪这个其他进程感兴趣”。它实际上不会导致其他进程退出,或导致您的进程等待。
如果要强制它们退出,则需要p.Kill()
在进程上使用该方法-但是请注意,杀死进程绝不是一个好主意,因为它们无法自行清理,并且可能会留下损坏的文件,并且很快。
如果您想等待他们自行退出,您可以使用p.WaitForExit()
- 但是这仅在您一次等待一个进程时才有效。如果你想同时等待它们,那就很棘手了。
通常你会使用WaitHandle.WaitAll
这个,但由于没有办法从 a 中WaitHandle
取出一个对象System.Diagnostics.Process
,你不能这样做(说真的,微软在想什么?)。
您可以为每个进程启动一个线程,并在这些线程中调用 `WaitForExit,但这也是错误的方法。
相反,您必须使用 p/invoke 来访问本机 win32WaitForMultipleObjects
功能。
这是一个示例(我已经测试过,并且确实有效)
[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
}