2008-10-02 8 views
8

J'essaie d'appeler php-cgi.exe à partir d'un programme .NET. J'utilise RedirectStandardOutput pour obtenir la sortie en tant que flux mais l'ensemble est très lent.Redirige la sortie standard efficacement dans .NET

Avez-vous une idée de comment je peux faire ça plus vite? Toute autre technique?

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

Vous pourriez être intéressé par [ce poste] (http://www.codeducky.org/process-handling-net), qui couvre la plupart des subtilités de travailler avec des flux de processus .NET. Il recommande la bibliothèque [MedallionShell] (https://github.com/madelson/MedallionShell), qui simplifie énormément ce type de tâche, et peut utiliser async pour empêcher le blocage – ChaseMedallion

Répondre

7

Vous pouvez utiliser le OutputDataReceived event pour recevoir des données comme il est pompé vers StdOut.

+0

Juste une note de côté, je voudrais rediriger l'erreur standard avec le OutputDataReceived événement aussi bien. Vous pouvez alors lancer une nouvelle exception ou gérer l'erreur d'une autre manière. –

+0

Excellent point! –

+8

@Vincent @Bob King Le problème avec cet événement est qu'il est seulement appelé quand la sortie reçoit une nouvelle ligne. Ma solution dans une autre réponse dans ce fil fonctionne également lorsque la sortie n'a pas de retour chariot ni de saut de ligne. –

15

La meilleure solution que j'ai trouvé est:

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

vous avez raison, cette solution est réselliente mais son importance n'est pas claire jusqu'à ce que vous passiez par le problème que vous avez décrit dans le commentaire sur la question –

+0

pouvez-vous bifurquer ou té la sortie de sorte qu'il va exécuter shell et votre processus en même temps temps? http://stackoverflow.com/questions/9525171/can-i-fork-the-output-streams-of-a-process-im-starting/9525264#comment12080971_9525264 – Maslow

+2

C'est littéralement la meilleure solution que j'ai jamais vue pour rediriger sortie ... merci Jader! – slashp

2

Le problème est dû une mauvaise configuration php.ini. J'ai eu le même problème et j'ai téléchargé le programme d'installation de Windows à partir de: http://windows.php.net/download/. Après cela et commenter les extensions non nécessaires, le processus de conversion est alà Speedy Gonzales, en convertissant 20 php par seconde.

Vous pouvez utiliser "oProcess.StandardOutput.ReadToEnd()" en toute sécurité. Il est plus lisible et plus rapide que l'utilisation de la solution de fil. Pour utiliser la solution de thread en conjonction avec une chaîne, vous devez introduire un événement ou quelque chose.

Vive

Questions connexes