我想等待一个进程完成,但process.WaitForExit()
挂起我的GUI.是否有基于事件的方式,或者我是否需要生成一个线程来阻止直到退出,然后自己委托事件?
从.NET 4.0/C#5开始,使用异步模式表示它更好.
////// Waits asynchronously for the process to exit. /// /// The process to wait for cancellation. /// A cancellation token. If invoked, the task will return /// immediately as canceled. ///A Task representing waiting for the process to end. public static Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default(CancellationToken)) { var tcs = new TaskCompletionSource
用法:
public async void Test() { var process = new Process("processName"); process.Start(); await process.WaitForExitAsync(); //Do some fun stuff here... }
process.EnableRaisingEvents = true;
process.Exited + = [EventHandler]
这是一个稍微清晰的扩展方法,因为它清除了取消令牌注册和退出事件.它还处理竞争条件边缘情况,其中进程可以在它开始之后但在连接Exited事件之前结束.它使用C#7中的新本地函数语法.
public static class ProcessExtensions { public static async Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default) { var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); void Process_Exited(object sender, EventArgs e) { tcs.TrySetResult(true); } process.EnableRaisingEvents = true; process.Exited += Process_Exited; try { if (process.HasExited) { return; } using (cancellationToken.Register(() => tcs.TrySetCanceled())) { await tcs.Task.ConfigureAwait(false); } } finally { process.Exited -= Process_Exited; } } }
如果你选择@MgSam答案,请注意,如果你通过了WaitForExitAsync
一些CancellationToken
,那将在指定的延迟后自动取消,你可以得到一个InvalidOperationException
.要解决这个问题,你需要改变
cancellationToken.Register(tcs.SetCanceled);
至
cancellationToken.Register( () => { tcs.TrySetCanceled(); } );
PS:别忘了及时处理你CancellationTokenSource
.