Como sugiere el título, ¿hay un equivalente a Process.Start
(le permite ejecutar otra aplicación o archivo por lotes) que pueda esperar?
Estoy jugando con una pequeña aplicación de consola y este parecía ser el lugar perfecto para usar async y esperar, pero no puedo encontrar ninguna documentación para este escenario.
Lo que estoy pensando es algo en este sentido:
void async RunCommand()
{
var result = await Process.RunAsync("command to run");
}
c#
async-await
c#-5.0
linkerro
fuente
fuente
Process.Start
es asíncrono y el OP parece querer una versión sincrónica.Respuestas:
Process.Start()
solo comienza el proceso, no espera hasta que termine, por lo que no tiene mucho sentido hacerloasync
. Si todavía quieres hacerlo, puedes hacer algo comoawait Task.Run(() => Process.Start(fileName))
.Pero, si desea esperar asincrónicamente a que finalice el proceso, puede usar el
Exited
evento junto conTaskCompletionSource
:fuente
process
yprocess.StartInfo
cambia lo que sucede cuando lo ejecuta.Start()
. Si, por ejemplo, llama.EnableRaisingEvents = true
antes de configurar lasStartInfo
propiedades como se ve aquí, las cosas funcionan como se espera. Si lo configura más tarde, por ejemplo, para mantenerlo junto.Exited
, aunque lo llame antes.Start()
, no funciona correctamente: se.Exited
dispara de inmediato en lugar de esperar a que el Proceso se cierre realmente. No sé por qué, solo una palabra de precaución.process.SynchronizingObject
debe establecerse en el componente de formularios para evitar que los métodos que manejan eventos (como Exited, OutputDataReceived, ErrorDataReceived) se invoquen en subprocesos separados.Process.Start
enTask.Run
. Una ruta UNC, por ejemplo, se resolverá sincrónicamente. Este fragmento puede tardar hasta 30 segundos en completarse:Process.Start(@"\\live.sysinternals.com\whatever")
Aquí está mi opinión, basada en la respuesta de svick . Agrega redirección de salida, retención de código de salida y un manejo de errores ligeramente mejor (desechando el
Process
objeto incluso si no se pudo iniciar):fuente
async Task<int> RunProcessAsync(string fileName, string args)
. Adapte este ejemplo y paso tres objetos uno por uno. ¿Cómo puedo esperar para levantar eventos? p.ej. antes de que mi aplicación se detenga ... muchas graciasDispose
anule el controlador de eventos, por lo que, en teoría, si llamóDispose
pero mantuvo la referencia, creo que sería una fuga. Sin embargo, cuando no hay más referencias alProcess
objeto y se obtiene (basura), no hay nadie que apunte a la lista de controladores de eventos. Por lo tanto, se recolecta, y ahora no hay referencias a los delegados que solían estar en la lista, por lo que finalmente se recolecta la basura.Dispose
limpia algunos recursos, pero no evita que se guarde una referencia filtradaprocess
. De hecho, notará que seprocess
refiere a los controladores, pero elExited
controlador también tiene una referenciaprocess
. En algunos sistemas, esa referencia circular evitaría la recolección de basura, pero el algoritmo utilizado en .NET aún permitiría que todo se limpiara siempre que todo viva en una "isla" sin referencias externas.Aquí hay otro enfoque. Concepto similar a las respuestas de svick y Ohad pero usando un método de extensión en el
Process
tipo.Método de extensión:
Ejemplo de caso de uso en un método contenedor:
fuente
He creado una clase para comenzar un proceso y fue creciendo en los últimos años debido a varios requisitos. Durante el uso descubrí varios problemas con la clase Process con la eliminación e incluso la lectura del ExitCode. Así que todo está arreglado por mi clase.
La clase tiene varias posibilidades, por ejemplo, leer la salida, comenzar como administrador o usuario diferente, capturar excepciones y también iniciar todo esto asíncrono incl. Cancelación. Lo bueno es que la salida de lectura también es posible durante la ejecución.
fuente
Creo que todo lo que debes usar es esto:
Ejemplo de uso:
fuente
CancellationToken
, si cancelarlo no esKill
el proceso?CancellationToken
en elWaitForExitAsync
método es necesario simplemente para poder cancelar una espera o establecer un tiempo de espera. La eliminación de un proceso se puede realizar enStartProcessAsync
: `` `` try {await process.WaitForExitAsync (cancellationToken); } catch (OperationCanceledException) {process.Kill (); } `` `CancellationToken
, cancelar el token debería resultar en la cancelación de la operación, no en la cancelación de la espera. Esto es lo que la persona que llama del método normalmente esperaría. Si la persona que llama desea cancelar solo la espera y dejar que la operación siga ejecutándose en segundo plano, es bastante fácil hacerlo externamente ( aquí hay un método de extensiónAsCancelable
que está haciendo exactamente eso).Estoy realmente preocupado por la eliminación del proceso, ¿qué pasa con la espera de salida asíncrona ?, esta es mi propuesta (basada en la anterior):
Luego, úsalo así:
fuente