process.WaitForExit () de forma assíncrona

Eu quero esperar por um processo para concluir, mas process.WaitForExit() trava minha GUI. Existe uma maneira baseada em events, ou eu preciso gerar um thread para bloquear até sair e delegar o evento eu mesmo?

process.EnableRaisingEvents = true;
process.Exited + = [EventHandler]

A partir do .NET 4.0 / C # 5, é melhor representá-lo usando o padrão asynchronous.

 ///  /// 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(); process.EnableRaisingEvents = true; process.Exited += (sender, args) => tcs.TrySetResult(null); if(cancellationToken != default(CancellationToken)) cancellationToken.Register(tcs.SetCanceled); return tcs.Task; } 

Uso:

 public async void Test() { var process = new Process("processName"); process.Start(); await process.WaitForExitAsync(); //Do some fun stuff here... } 

Se você escolher a resposta @MgSam, esteja ciente, se você passar por WaitForExitAsync algum CancellationToken , que será automaticamente cancelado após o atraso especificado, você poderá obter uma InvalidOperationException . Para corrigir isso, você precisa mudar

 cancellationToken.Register(tcs.SetCanceled); 

para

 cancellationToken.Register( () => { tcs.TrySetCanceled(); } ); 

PS: não esqueça de descartar seu CancellationTokenSource tempo.

De acordo com esse link, o método WaitForExit () é usado para fazer o thread atual aguardar até que o processo associado termine. No entanto, o processo tem um evento Exited que você pode conectar.

Aqui está um método de extensão que é um pouco mais limpo, porque limpa o registro de token de cancelamento e o evento Exited. Ele também lida com o caso de borda de condição de corrida, onde o processo pode terminar depois de iniciado, mas antes do evento Exited ser anexado. Ele usa a nova syntax de funções locais em C # 7.

 public static class ProcessExtensions { public static async Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default) { var tcs = new TaskCompletionSource(); 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; } } finally { process.Exited -= Process_Exited; } } } 

Use System.Diagnostics.Process.Exited