Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

273
Vistas
¿Cómo puedo leer de manera confiable el resultado completo de un proceso en C# al proporcionar un tiempo de espera máximo para WaitForExit()?

Considere el siguiente programa. Aquí empiezo un proceso simple y quiero lidiar con su salida. Supuse que ese sería el caso después de que WaitForExit haya regresado, pero resulta que tengo que esperar hasta un segundo completo hasta que esa salida realmente llegue a mi programa.

 static void Main(string[] args) { using var p = new Process(); p.StartInfo.FileName = "echo"; p.StartInfo.Arguments = "I apologize for being late"; p.StartInfo.CreateNoWindow = false; p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; var stdError = new StringBuilder(); var stdOutput = new StringBuilder(); p.ErrorDataReceived += (sender, args) => stdError.AppendLine(args.Data); p.OutputDataReceived += (sender, args) => stdOutput.AppendLine(args.Data); p.Start(); p.BeginErrorReadLine(); p.BeginOutputReadLine(); // without the int-parameter here, it works while (!p.WaitForExit(10000)) Console.WriteLine("still waiting..."); string a = stdOutput.ToString(); string b = stdError.ToString(); Thread.Sleep(1000); string c = stdOutput.ToString(); string d = stdError.ToString(); Console.WriteLine("output before sleep: " + a); Console.WriteLine("error before sleep: " + b); Console.WriteLine("output after sleep: " + c); Console.WriteLine("error after sleep: " + d); }

producción

 output before sleep: error before sleep: output after sleep: I apologize for being late error after sleep:

Aquí esperaría que a y c tengan exactamente el mismo valor. Pero ese no es el caso. ¿Cómo modificaría este ejemplo de manera que reciba de manera confiable el resultado completo del proceso, pero sin llamar a Thread.Sleep(1000) ?

Notas:

  • Quiero la salida completa confiable de stdOut y stdErr
  • cuando uso p.WaitForExit() en lugar p.WaitForExit(10000) todo parece funcionar
  • Cuando se usa p.StandardOutput.ReadToEnd() para ambas transmisiones, parece funcionar. Pero la documentación oficial me dice que esto conduciría a puntos muertos.
  • cuando se usa p.StandardError.ReadToEnd() mientras se usa la solución asíncrona para la salida, la salida aún llega tarde.
  • esto no es un duplicado de Process WaitForExit que no espera porque para ellos p.WaitForExit() sin ningún parámetro ya no funciona. Además, no están interesados en la salida en absoluto.
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Hay un detalle de implementación incómodo que está en juego aquí.

Vocación

 p.WaitForExit();

y

 p.WaitForExit(10000);

hacer cosas ligeramente diferentes cuando se señala el controlador de proceso nativo real.

Internamente p.WaitForExit(); llama a p.WaitForExit(-1); . El -1 es significativo aquí. Veamos qué tenemos (el código está simplificado/parafraseado para mostrar la esencia):

 public bool WaitForExit(int milliseconds) { // init stuff removed bool flag; try { flag = processWaitHandle.WaitOne(milliseconds, false); } finally { // here we see our -1 return if (this.output != null && milliseconds == -1) { this.output.WaitUtilEOF(); } } return flag; }

En el fragmento anterior, verá this.output.WaitUtilEOF(); y eso llama a un AsyncStreamReader interno que emplea una cola. La llamada a WaitUtilEOF(); básicamente espera en la transmisión a que se genere el evento EOF.

No hay otra forma que pueda encontrar para obligar a la clase Process a hacer una llamada para esperar esos eventos EOF. La única opción es llamar a WaitForExit() sin un parámetro. Sin embargo, no hay penalización por llamar a WaitForExit(); después de una llamada a WaitForExit(10000) devuelta.

Entonces, si se alcanzó el tiempo de espera en el primer WaitForExit(10000) pero está seguro de que prefiere esperar un poco más para que AsyncStreamReader le entregue todos los datos que tiene, llame a WaitForExit() sin un parámetro para que ambos AsyncStreamReaders vacíen su cola y luego te devuelvo el control. Esto significa que si su proceso no finalizó, ahora está atrapado en una espera que nunca se resolverá a menos que elimine el proceso secundario usted mismo.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda