Nennen wir den hier veröffentlichten Beispielcode den Redirector und das andere Programm den Redirector. Wenn ich es wäre, würde ich wahrscheinlich ein Testumleitungsprogramm schreiben, mit dem das Problem dupliziert werden kann.
So tat ich. Für Testdaten habe ich die PDF-Datei ECMA-334 C # verwendet. es ist ungefähr 5 MB. Das Folgende ist der wichtige Teil davon.
StreamReader stream = null;
try { stream = new StreamReader(Path); }
catch (Exception ex)
{
Console.Error.WriteLine("Input open error: " + ex.Message);
return;
}
Console.SetIn(stream);
int datasize = 0;
try
{
string record = Console.ReadLine();
while (record != null)
{
datasize += record.Length + 2;
record = Console.ReadLine();
Console.WriteLine(record);
}
}
catch (Exception ex)
{
Console.Error.WriteLine($"Error: {ex.Message}");
return;
}
Der Datengrößenwert stimmt nicht mit der tatsächlichen Dateigröße überein, dies spielt jedoch keine Rolle. Es ist nicht klar, ob eine PDF-Datei am Ende der Zeilen immer sowohl CR als auch LF verwendet, aber das spielt dabei keine Rolle. Sie können jede andere große Textdatei zum Testen verwenden.
Dabei hängt der Beispiel-Redirector-Code, wenn ich die große Datenmenge schreibe, aber nicht, wenn ich eine kleine Menge schreibe.
Ich habe sehr viel versucht, die Ausführung dieses Codes irgendwie zu verfolgen, und ich konnte es nicht. Ich habe die Zeilen des umgeleiteten Programms auskommentiert, die die Erstellung einer Konsole für das umgeleitete Programm deaktiviert haben, um zu versuchen, ein separates Konsolenfenster zu erhalten, konnte dies jedoch nicht.
Dann fand ich heraus, wie man eine Konsolen-App in einem neuen Fenster, im Fenster der Eltern oder in keinem Fenster startet . Anscheinend können wir keine (einfache) separate Konsole haben, wenn ein Konsolenprogramm ein anderes Konsolenprogramm ohne ShellExecute startet. Da ShellExecute die Umleitung nicht unterstützt, müssen wir eine Konsole freigeben, auch wenn wir kein Fenster für den anderen Prozess angeben.
Ich gehe davon aus, dass das umgeleitete Programm, wenn es irgendwo einen Puffer füllt, auf das Lesen der Daten warten muss. Wenn zu diesem Zeitpunkt keine Daten vom Redirector gelesen werden, ist dies ein Deadlock.
Die Lösung besteht darin, ReadToEnd nicht zu verwenden und die Daten zu lesen, während die Daten geschrieben werden. Es ist jedoch nicht erforderlich, asynchrone Lesevorgänge zu verwenden. Die Lösung kann recht einfach sein. Das Folgende funktioniert für mich mit dem 5 MB PDF.
ProcessStartInfo info = new ProcessStartInfo(TheProgram);
info.CreateNoWindow = true;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Process p = Process.Start(info);
string record = p.StandardOutput.ReadLine();
while (record != null)
{
Console.WriteLine(record);
record = p.StandardOutput.ReadLine();
}
p.WaitForExit();
Eine andere Möglichkeit besteht darin, ein GUI-Programm zu verwenden, um die Umleitung durchzuführen. Der vorhergehende Code funktioniert in einer WPF-Anwendung, außer mit offensichtlichen Änderungen.