Nazwijmy zamieszczony tutaj przykładowy kod redirectorem, a drugi program przekierowanym. Gdybym to był ja, prawdopodobnie napisałbym program przekierowany testowo, który można wykorzystać do powielenia problemu.
Więc zrobiłem. Do danych testowych użyłem specyfikacji języka ECMA-334 C # v PDF; jest to około 5 MB. Poniżej znajduje się ważna część tego.
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;
}
Wartość rozmiaru danych nie odpowiada rzeczywistemu rozmiarowi pliku, ale to nie ma znaczenia. Nie jest jasne, czy plik PDF zawsze używa na końcu linii zarówno CR, jak i LF, ale nie ma to znaczenia. Możesz użyć dowolnego innego dużego pliku tekstowego do przetestowania.
Korzystając z tego, przykładowy kod readresatora zawiesza się, gdy piszę dużą ilość danych, ale nie podczas pisania małej ilości.
Bardzo starałem się jakoś prześledzić wykonanie tego kodu i nie mogłem. Skomentowałem wiersze przekierowanego programu, który wyłączał tworzenie konsoli dla przekierowanego programu, aby spróbować uzyskać oddzielne okno konsoli, ale nie mogłem.
Potem znalazłem Jak uruchomić aplikację konsolową w nowym oknie, w oknie rodzica lub bez okna . Tak więc najwyraźniej nie możemy (łatwo) mieć oddzielnej konsoli, gdy jeden program konsoli uruchamia inny program konsoli bez ShellExecute, a ponieważ ShellExecute nie obsługuje przekierowywania, musimy udostępniać konsolę, nawet jeśli nie określimy okna dla drugiego procesu.
Zakładam, że jeśli przekierowany program zapełnia gdzieś bufor, to musi czekać na odczytanie danych i jeśli w tym momencie żadne dane nie są odczytywane przez readresator, to jest to zakleszczenie.
Rozwiązaniem jest nieużywanie ReadToEnd i odczytywanie danych podczas ich zapisywania, ale nie jest konieczne stosowanie odczytów asynchronicznych. Rozwiązanie może być całkiem proste. Poniższe działa dla mnie z 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();
Inną możliwością jest użycie programu GUI do wykonania przekierowania. Poprzedni kod działa w aplikacji WPF z wyjątkiem oczywistych modyfikacji.