注:この質問は最初のバージョンから大幅に変更されているため、コメントや回答が奇妙に見える場合があります。おかしなところがあれば編集履歴を確認してください。
C# クラス ライブラリから子プロセスを起動しています。
Process.BeginOutputReadLine()
出力/エラーを非同期で読み取るために使用しています。非常に長い行では機能しないと思っていましたが、スケーラブルではないことが問題のようです。私のコンピューターでは、128 kb の行は即座に処理され、512 kb の行は約 1 分かかるようで、1 mb は数分かかるようで、10 mb の行が処理されるのを約 2 時間待ちました。私がキャンセルしたとき、それはまだ働いていました。
StandardOutput および StandardError ストリームからの直接読み取りを修正するのは簡単に思えますが、これらのストリームからのデータはバッファリングされているようです。標準出力からバッファを埋めるのに十分なデータを取得してから、標準エラー出力からさらにデータを取得した場合、それらのいずれかに保留中のデータがあるかどうかを確認する方法が見つかりません。標準エラー出力から読み取ろうとすると、ハングします永遠に。なぜこれが起こっているのか、何が間違っているのか、これを行う正しい方法は何ですか?
私が達成しようとしていることを説明するためのいくつかのコードサンプル。
Program1
:
// Writes a lot of data to stdout and stderr static void Main(string[] args) { int numChars = 512 * 1024; StringBuilder sb = new StringBuilder(numChars); String s = "1234567890"; for (int i = 0; i < numChars; i++) sb.Append(s[i % 10]); int len = sb.Length; Console.WriteLine(sb.ToString()); Console.Error.WriteLine(sb.ToString()); }
Program2
:
// Calls Program1 and tries to read its output. static void Main(string[] args) { StringBuilder sb = new StringBuilder(); StringBuilder sbErr = new StringBuilder(); proc.StartInfo.CreateNoWindow = true; proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardError = true; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardInput = false; proc.StartInfo.Arguments = ""; proc.StartInfo.FileName = "program1.exe"; proc.ErrorDataReceived += (s, ee) => { if (ee.Data != null) sbErr.AppendLine(ee.Data); }; proc.OutputDataReceived += (s, ee) => { if (ee.Data != null) sb.AppendLine(ee.Data); }; proc.Start(); proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); proc.WaitForExit(); }
Program1
生成するデータのサイズを設定できる定数があり、Program2
起動Program1
してデータの読み取りを試みます。時間がサイズに比例して増加すると予想する必要がありますが、それよりもはるかに悪いようです.