2009-01-22 10 views
21

Je souhaite attendre la fin d'un processus, mais process.WaitForExit() bloque mon interface graphique. Y a-t-il un moyen basé sur les événements, ou dois-je générer un thread pour bloquer jusqu'à la sortie, puis déléguer l'événement moi-même?process.WaitForExit() asynchrone

+0

Voici une implémentation ** entièrement asynchrone ** de 'Process' qui vous permet également de rediriger la sortie standard et les flux d'erreur standard http://stackoverflow.com/a/39872058/1212017. –

Répondre

1

utilisation System.Diagnostics.Process.Exited

4

According to this link la méthode WaitForExit() est utilisée pour fabriquer le fil en cours d'attente jusqu'à ce que le processus associé se termine. Toutefois, le processus a un événement Exited que vous pouvez connecter.

+3

Qu'est-ce que c'est alors? http://msdn.microsoft.com/en-us/library/system.diagnostics.process.exited.aspx –

+0

Pas vrai, la réponse devrait être supprimée pour ne pas collenter downvotes je suppose. –

55

A partir de .NET 4.0/C# 5, il est plus agréable de représenter cela en utilisant le modèle async.

/// <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; 
} 

Utilisation:

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

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

Merci, ce fut utile. Une chose avec laquelle j'ai eu des pourparlers, cependant, est que 'tcs.SetResult (null)' lance une exception 'InvalidOperationException' si la tâche a déjà été annulée, ce qui peut arriver si le processus se termine après l'annulation de la tâche. Pour résoudre ce problème, j'ai remplacé 'tcs.SetResult' par' tcs.TrySetResult'. –

+0

@aj_r Bon conseil. Merci. J'ai fait la mise à jour. – MgSam

+4

Si le processus s'arrête avant d'enregistrer notre gestionnaire Exited, nous attendons toujours. L'enregistrement doit être fait avant le démarrage, donc il est beaucoup plus facile d'écrire une méthode StartAsync. Principalement le même code mais nommé StartAsync avec un process.Start() juste avant la ligne de retour. – MuiBienCarlota

6

Si vous choisissez réponse @MgSam, sachez, si vous passez par WaitForExitAsync certains CancellationToken, qui sera automatiquement annulée après le délai spécifié, vous pouvez obtenir un InvalidOperationException. Pour résoudre ce problème, vous devez changer

cancellationToken.Register(tcs.SetCanceled); 

à

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

P.S .: ne pas oublier de jeter votre CancellationTokenSource dans le temps.

+0

That P.S. sauvé ma vie.... – Fazi