2009-01-22 2 views
21

Я хочу дождаться завершения процесса, но process.WaitForExit() висит в моем графическом интерфейсе. Есть ли способ, основанный на событиях, или мне нужно порождать поток для блокировки до выхода, а затем делегировать событие самостоятельно?process.WaitForExit() асинхронно

+0

Настоящая ** реализация async ** 'Process', которая позволяет также перенаправить стандартные выходные и стандартные потоки ошибок http://stackoverflow.com/a/39872058/1212017. –

ответ

4

According to this link метод использования System.Diagnostics.Process.Exited WaitForExit() используется, чтобы сделать текущее ожидание нити до тех пор, пока связанный с ним процесс завершается. Тем не менее, процесс имеет событие «Выход», в которое вы можете подключиться.

+3

Что это? http://msdn.microsoft.com/en-us/library/system.diagnostics.process.exited.aspx –

+0

Неверно, ответ должен быть удален, чтобы не совпадал с downvotes. –

55

С .NET 4.0/C# 5, это лучше, чтобы представить это, используя шаблон асинхронной.

/// <summary> 
/// Waits asynchronously for the process to exit. 
/// </summary> 
/// <param name="process">The process to wait for cancellation.</param> 
/// <param name="cancellationToken">A cancellation token. If invoked, the task will return 
/// immediately as canceled.</param> 
/// <returns>A Task representing waiting for the process to end.</returns> 
public static Task WaitForExitAsync(this Process process, 
    CancellationToken cancellationToken = default(CancellationToken)) 
{ 
    var tcs = new TaskCompletionSource<object>(); 
    process.EnableRaisingEvents = true; 
    process.Exited += (sender, args) => tcs.TrySetResult(null); 
    if(cancellationToken != default(CancellationToken)) 
     cancellationToken.Register(tcs.SetCanceled); 

    return tcs.Task; 
} 

Использование:

public async void Test() 
{ 
    var process = new Process("processName"); 
    process.Start(); 
    await process.WaitForExitAsync(); 

    //Do some fun stuff here... 
} 
+1

Спасибо, это было полезно. Одна вещь, с которой я столкнулся, заключается в том, что 'tcs.SetResult (null)' выдает 'InvalidOperationException', если задача уже отменена, что может произойти, если процесс завершается после отмены задачи. Чтобы исправить это, я заменил 'tcs.SetResult' на' tcs.TrySetResult'. –

+0

@aj_r Хороший совет. Благодарю. Я сделал обновление. – MgSam

+4

Если процесс остановится, прежде чем мы зарегистрируем наш обработчик Exited, мы будем ждать навсегда. Регистрация должна быть выполнена до начала, так что гораздо проще написать метод StartAsync. В основном такой же код, но с именем StartAsync с process.Start() juste перед обратной линией. – MuiBienCarlota

6

Если вы выбираете @MgSam ответ, быть в курсе, если вы проходите через WaitForExitAsync некоторые CancellationToken, которые будут автоматически отменены после указанной задержки, вы можете получить InvalidOperationException. Чтобы исправить это, вам нужно изменить

cancellationToken.Register(tcs.SetCanceled); 

к

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

P.S .: Не забудьте утилизировать свой CancellationTokenSource вовремя.

+0

Это P.S. спас мою жизнь.... – Fazi

Смежные вопросы