Comme le titre l'indique, y a-t-il un équivalent à Process.Start
(vous permet d'exécuter une autre application ou un autre fichier batch) que je peux attendre?
Je joue avec une petite application console et cela semblait être l'endroit idéal pour utiliser async et attendre, mais je ne trouve aucune documentation pour ce scénario.
Ce que je pense, c'est quelque chose du genre:
void async RunCommand()
{
var result = await Process.RunAsync("command to run");
}
c#
async-await
c#-5.0
linkerro
la source
la source
Process.Start
c'est asynchrone et l'OP semble vouloir une version synchrone.Réponses:
Process.Start()
ne fait que démarrer le processus, il n'attend pas qu'il se termine, donc cela n'a pas beaucoup de sens de le faireasync
. Si vous voulez toujours le faire, vous pouvez faire quelque chose commeawait Task.Run(() => Process.Start(fileName))
.Mais, si vous souhaitez attendre de manière asynchrone la fin du processus, vous pouvez utiliser l'
Exited
événement avecTaskCompletionSource
:la source
process
etprocess.StartInfo
change ce qui se passe lorsque vous l'exécutez avec.Start()
. Si vous appelez par exemple.EnableRaisingEvents = true
avant de définir lesStartInfo
propriétés comme indiqué ici, les choses fonctionnent comme prévu. Si vous le définissez plus tard, par exemple pour le conserver avec.Exited
, même si vous l'appelez auparavant.Start()
, il ne fonctionne pas correctement - se.Exited
déclenche immédiatement au lieu d'attendre que le processus se termine réellement. Je ne sais pas pourquoi, juste un mot d'avertissement.process.SynchronizingObject
doit être défini sur le composant de formulaires pour éviter que les méthodes qui gèrent les événements (comme Exited, OutputDataReceived, ErrorDataReceived) ne soient appelées sur un thread séparé.Process.Start
dansTask.Run
. Un chemin UNC, par exemple, sera résolu de manière synchrone. Cet extrait peut prendre jusqu'à 30 secondes pour se terminer:Process.Start(@"\\live.sysinternals.com\whatever")
Voici mon avis, basé sur la réponse de svick . Il ajoute la redirection de sortie, la rétention du code de sortie et une gestion des erreurs légèrement meilleure (en supprimant l'
Process
objet même s'il n'a pas pu être démarré):la source
async Task<int> RunProcessAsync(string fileName, string args)
. J'ai adapté cet exemple et passé trois objets un par un. Comment puis-je attendre de lever des événements? par exemple. avant que mon application ne s'arrête .. merci beaucoupDispose
le gestionnaire d'événements annule, donc théoriquement si vous avez appeléDispose
mais gardé la référence, je pense que ce serait une fuite. Cependant, lorsqu'il n'y a plus de références à l'Process
objet et qu'il est (garbage) collecté, personne ne pointe vers la liste des gestionnaires d'événements. Donc, il est collecté, et maintenant il n'y a plus de références aux délégués qui étaient dans la liste, donc finalement ils sont récupérés.Dispose
nettoie certaines ressources, mais n'empêche pas une référence divulguée de resterprocess
. En fait, vous remarquerez que celaprocess
fait référence aux gestionnaires, mais leExited
gestionnaire a également une référence àprocess
. Dans certains systèmes, cette référence circulaire empêcherait le garbage collection, mais l'algorithme utilisé dans .NET permettrait toujours de tout nettoyer tant que tout vit sur un «îlot» sans références extérieures.Voici une autre approche. Concept similaire aux réponses de svick et Ohad mais en utilisant une méthode d'extension sur le
Process
type.Méthode d'extension:
Exemple de cas d'utilisation dans une méthode contenant:
la source
J'ai construit une classe pour démarrer un processus et elle s'est développée au cours des dernières années en raison de diverses exigences. Pendant l'utilisation, j'ai découvert plusieurs problèmes avec la classe Process avec l'élimination et même la lecture de l'ExitCode. Donc, tout est réglé par ma classe.
La classe a plusieurs possibilités, par exemple lire la sortie, démarrer en tant qu'administrateur ou utilisateur différent, attraper des exceptions et également démarrer tout cela incl. Asynchrone. Annulation. Bien, la lecture de la sortie est également possible pendant l'exécution.
la source
Je pense que tout ce que vous devriez utiliser est ceci:
Exemple d'utilisation:
la source
CancellationToken
, si l'annulation ne résout pasKill
le processus?CancellationToken
dans laWaitForExitAsync
méthode est nécessaire simplement pour pouvoir annuler une attente ou définir un délai. Tuer un processus peut être fait dansStartProcessAsync
: `` `` try {wait process.WaitForExitAsync (cancelToken); } catch (OperationCanceledException) {process.Kill (); } `` ``CancellationToken
, l'annulation du token devrait entraîner l'annulation de l'opération, pas l'annulation de l'attente. C'est ce à quoi s'attendrait normalement l'appelant de la méthode. Si l'appelant souhaite annuler uniquement l'attente et laisser l'opération s'exécuter en arrière-plan, il est assez facile de le faire en externe ( voici une méthode d'extensionAsCancelable
qui fait exactement cela).Je suis vraiment inquiet pour l'élimination du processus, qu'en est-il d'attendre la sortie asynchrone ?, voici ma proposition (basée sur la précédente):
Ensuite, utilisez-le comme ceci:
la source