7

que leer la documentación de Process.StandardOutput, que cuenta con esta cita:¿Manera correcta de manejar el error estándar y la salida de un programa cuando se generó a través de la clase de proceso desde C#?

Una condición de interbloqueo puede resultar si el proceso padre llama p.WaitForExit antes p.StandardOutput.ReadToEnd y el proceso de niño escribe texto suficiente para llenar el redirigida corriente.

Así que me pregunto. ¿Cuál es la forma correcta de hacer esto si también tengo miedo de que StandardError se pueda completar en algunos escenarios?

¿Tengo que utilizar un bucle para alternar la lectura de salida estándar y error, para evitar o bien llenando, o es el código bastante simple:

string error = proc.StandardError.ReadToEnd(); 
string output = proc.StandardOutput.ReadToEnd(); 
bool didFinish = proc.WaitForExit(60000); 

Editado después de algunas respuestas han sido publicado

Así que este es el enfoque correcto?

var output = new StringBuilder(); 
proc.OutputDataReceived += (s, e) => output.Append(e.Data); 
proc.BeginOutputReadLine(); 
string error = proc.StandardError.ReadToEnd(); 
bool didFinish = proc.WaitForExit(60000); 

Y luego uso el contenido de stringbuilder solo si el proceso realmente finalizó.

es que el enfoque en ese momento?

+0

Compruebe la respuesta http: // stackoverflow.com/a/7608823/276648 – user276648

Respuesta

6

Su código de ejemplo podría provocar un estancamiento situtation donde había algo escrito a la StandardOutput y no a StandardError. El siguiente ejemplo de la documentación que vinculó indica tanto.

Esencialmente, lo que recomendaría es utilizar las lecturas asíncronas en ambas transmisiones para llenar un búfer a medida que se escriben las Corrientes, y luego llamar al WaitForExit.

+0

Sí, me interesa saber por qué no utiliza este método como el que se proporciona en MSDN '. Puede utilizar operaciones de lectura asíncrona para evitar estas dependencias y su potencial de interbloqueo. Alternativamente, puede evitar la condición de interbloqueo creando dos subprocesos y leyendo la salida de cada secuencia en un subproceso separado. – jcolebrand

+0

Editado en código utilizando BeginOutputReadLine y OutputDataReceived, ¿puede echar un vistazo y ver si el código publicado es correcto? –

+0

Esto es lo que terminé con: http://bitbucket.org/lassevk/mercurial.net/src/728f85d67447/Mercurial.Net/ClientWrapper.cs#cl-111 –

3

El problema surge debido a que el proceso hijo escribe su salida estándar y el error estándar en un par de tubos, que se dan un tampón finito por el sistema operativo. Si el padre no está leyendo activamente a ambos, es probable que se llenen. Cuando una tubería se llena, las escrituras subsiguientes se bloquean.

En su ejemplo, usted está leyendo todos los StandardError y todos StandardOutput. Esto funciona bien si el proceso secundario solo escribe un poco de datos en StandardError y/o StandardOutput. Es un problema si el proceso secundario desea escribir muchos datos en StandardOutput. Mientras el proceso primario está esperando consumir datos del StandardError, el proceso hijo está ocupado llenando el buffer StandardOutput.

La forma más segura es leer desde la entrada estándar y el error estándar al mismo tiempo. Hay algunas maneras de hacer esto:

  • hilos separados desovar y llaman ReadToEnd en cada
  • Uso BeginRead y EndRead en un hilo
  • agregar controladores en los Process.ErrorDataReceived y Process.OutputDataReceived eventos, a continuación, llamar Process.BeginErrorReadLine y Process.BeginOutputReadLine.
Cuestiones relacionadas