7

次の引用があるProcess.StandardOutputのドキュメントを読みました。

親プロセスが p.StandardOutput.ReadToEnd の前に p.WaitForExit を呼び出し、子プロセスがリダイレクトされたストリームを満たすのに十分なテキストを書き込むと、デッドロック状態が発生する可能性があります。

だから私は疑問に思っています。いくつかのシナリオで StandardError が満たされる可能性があることも恐れている場合、これを行う正しい方法は何ですか?

いっぱいになるのを避けるために、ループを使用して標準出力とエラーからの読み取りを交互に行う必要がありますか、それともこの単純なコードで十分ですか:

string error = proc.StandardError.ReadToEnd();
string output = proc.StandardOutput.ReadToEnd();
bool didFinish = proc.WaitForExit(60000);

いくつかの回答が投稿された後に編集されました

それで、これは正しいアプローチですか?

var output = new StringBuilder();
proc.OutputDataReceived += (s, e) => output.Append(e.Data);
proc.BeginOutputReadLine();
string error = proc.StandardError.ReadToEnd();
bool didFinish = proc.WaitForExit(60000);

そして、プロセスが実際に終了した場合にのみ、stringbuilder コンテンツを使用します。

それは正しいアプローチですか?

4

2 に答える 2

7

StandardOutputあなたのコード例は、 ではなくに何かが書き込まれたデッドロック状況を引き起こす可能性がありStandardErrorます。リンクしたドキュメントの次の例は、同様に述べています。

基本的に、私がお勧めするのは、ストリームが書き込まれるときに両方のストリームで非同期読み取りを使用してバッファーを埋め、次に を呼び出すことWaitForExitです。

于 2010-11-09T19:03:11.860 に答える
3

この問題が発生するのは、子プロセスがその標準出力と標準エラーを、OS によって有限のバッファーが与えられた一対のパイプに書き込むためです。親が両方を積極的に読んでいない場合、それらはいっぱいになる可能性があります。パイプがいっぱいになると、それ以降のパイプへの書き込みはブロックされます。

あなたの例では、 のStandardErrorすべてを読んでいますStandardOutputStandardError子プロセスがand/orに少量のデータを書き込むだけであれば、これは問題なく機能しますStandardOutput。子プロセスが に大量のデータを書き込もうとしている場合は問題ですStandardOutput。親プロセスが からのデータの消費を待機している間、子プロセスはビジー状態でバッファStandardErrorをいっぱいにしています。StandardOutput

最も安全な方法は、標準入力と標準エラーから同時に読み取ることです。これを行うにはいくつかの方法があります。

  • 個別のスレッドを生成ReadToEndし、それぞれを呼び出します
  • BeginReadandEndReadを 1 つのスレッドで使用する
  • Process.ErrorDataReceivedおよびイベントにハンドラーを追加してから、およびProcess.OutputDataReceivedを呼び出します。Process.BeginErrorReadLineProcess.BeginOutputReadLine
于 2010-11-09T19:01:58.027 に答える