2008-10-02 13 views
8

Estoy tratando de llamar a php-cgi.exe desde un programa .NET. Utilizo RedirectStandardOutput para recuperar la salida como una secuencia, pero todo es muy lento.Redirigir la salida estándar de manera eficiente en .NET

¿Tiene alguna idea de cómo puedo hacerlo más rápido? ¿Alguna otra técnica?

Dim oCGI As ProcessStartInfo = New ProcessStartInfo() 
    oCGI.WorkingDirectory = "C:\Program Files\Application\php" 
    oCGI.FileName = "php-cgi.exe" 
    oCGI.RedirectStandardOutput = True 
    oCGI.RedirectStandardInput = True 
    oCGI.UseShellExecute = False 
    oCGI.CreateNoWindow = True 

    Dim oProcess As Process = New Process() 

    oProcess.StartInfo = oCGI 
    oProcess.Start() 

    oProcess.StandardOutput.ReadToEnd() 
+0

que podría estar interesado en [este mensaje] (http://www.codeducky.org/process-handling-net), que cubre muchas de las complejidades de trabajar con corrientes de proceso .NET. Recomienda la biblioteca [MedallionShell] (https://github.com/madelson/MedallionShell), que simplifica enormemente este tipo de tarea, y puede usar async para evitar el bloqueo – ChaseMedallion

Respuesta

7

Puede utilizar el OutputDataReceived event para recibir datos, ya que es bombeada hacia la salida estándar.

+0

Solo una nota al margen, redirigiría el error estándar con el OutputDataReceived evento también. Luego podría lanzar una nueva excepción o manejar el error de otra manera. –

+0

¡Excelente punto! –

+8

@Vincent @Bob King El problema con este evento es que solo se llama cuando una salida recibe una nueva línea. Mi solución en otra respuesta en este hilo también funciona cuando la salida no tiene retornos de carro ni nuevas líneas. –

15

La mejor solución que he encontrado es:

private void Redirect(StreamReader input, TextBox output) 
{ 
    new Thread(a => 
    { 
     var buffer = new char[1]; 
     while (input.Read(buffer, 0, 1) > 0) 
     { 
      output.Dispatcher.Invoke(new Action(delegate 
      { 
       output.Text += new string(buffer); 
      })); 
     }; 
    }).Start(); 
} 

private void Window_Loaded(object sender, RoutedEventArgs e) 
{ 
    process = new Process 
    { 
     StartInfo = new ProcessStartInfo 
     { 
      CreateNoWindow = true, 
      FileName = "php-cgi.exe", 
      RedirectStandardOutput = true, 
      UseShellExecute = false, 
      WorkingDirectory = @"C:\Program Files\Application\php", 
     } 
    }; 
    if (process.Start()) 
    { 
     Redirect(process.StandardOutput, textBox1); 
    } 
} 
+0

tiene razón, esta solución es reseliente pero su importancia no está clara hasta que resuelva el problema que describió en el comentario sobre la pregunta –

+0

¿puede bifurcar o dar salida a la salida para que se ejecute y su proceso al mismo ¿hora? http://stackoverflow.com/questions/9525171/can-i-fork-the-output-streams-of-a-process-im-starting/9525264#comment12080971_9525264 – Maslow

+2

Esta es literalmente la mejor solución que he visto para redirigir salida ... gracias Jader! – slashp

2

El problema es debido una mala configuración php.ini. Tuve el mismo problema y descargué el instalador de Windows desde: http://windows.php.net/download/.

Después de eso y comentando las extensiones no necesarias, el proceso de conversión es al igual que Speedy Gonzales, convirtiendo 20 php por segundo.

Puede usar "oProcess.StandardOutput.ReadToEnd()" de forma segura. Es más legible y casi tan rápido como usar la solución de subprocesos. Para usar la solución de hilo junto con una cadena, debe introducir un evento o algo.

Saludos

Cuestiones relacionadas