2009-09-25 19 views
7

私は、コードのこの部分はデッドロック引き起こす可能性があることread: 親プロセスが子プロセスが十分なテキストを書き込みp.WaitForExitp.StandardOutput.ReadToEnd前 と を呼び出す場合、デッドロック状態が発生することができますProcess.StandardOutput.ReadToEnd();のDeadLockの問題

ので

Process p = new Process(); 

p.StartInfo.UseShellExecute = false; 
p.StartInfo.RedirectStandardOutput = true; 
p.StartInfo.FileName = "Write500Lines.exe"; 
p.Start(); 
p.WaitForExit(); 
string output = p.StandardOutput.ReadToEnd(); 

を リダイレクトされたストリームを入力します。子プロセスが終了するの 親プロセスは、無期限に 待機していました。 子プロセスがフル StandardOutputストリームから読み取るために無期限 親のために待機していました。

しかし、私はなく、かなりなぜ。つまり、ここでは、親プロセスとは何ですか、そしてその子は何ですか?

+1

あなたは、.NETプロセスストリームでの作業のデッドロックやその他の複雑さを説明している、[このポスト](http://www.codeducky.org/process-handling-net)に興味があるかもしれません。 – ChaseMedallion

答えて

11

これは何が起こるかです:

アプリケーションA(上記のコードは)子プロセスBを起動し、標準出力をリダイレクトします。次に、Aプロセスが終了するのを待ちます。 AがBを終了するのを待つ間、Bは出力ストリーム(Aがリダイレクトしたもの)に出力を生成します。このストリームのバッファサイズは制限されています。バッファがいっぱいになると、Bに書き込みを続けるためにバッファを空にする必要があります。 Bが終了するまで、Aは読み込みを行わないので、Bは出力バッファが空になるのを待つが、AはBが終了するのを待つ。両方ともお互いが行動するのを待っており、あなたはデッドロックしています。

あなたは、問題を示すために、次のコードを試すことができます(この場合は"cmd"で)子プロセスが待機するように

ProcessStartInfo psi = new ProcessStartInfo(); 
psi.FileName = "cmd"; 
psi.Arguments = @"/c dir C:\windows /s"; 
psi.RedirectStandardOutput = true; 
psi.UseShellExecute = false; 
Process p = Process.Start(psi); 
p.WaitForExit(); 
string output = p.StandardOutput.ReadToEnd(); 

は、これは(おそらくMOSTE)出力ストリームがいっぱいになっている状況を生成します上記のコードはcmdが終了するのを待つ間にクリアされます。

+0

あなたの明快な説明に感謝します。 – Graviton

+0

だから... ...どのように私ははるかに長い5分以上、そのようないないため、いくつかの引数を持つ 'sqlcmd.exe'などのプロセスを実行すると、私はキャプチャすることができますようstdoutとstderrの多くを読むことができますか?私はこれを行うためのきれいで簡単な方法を見つけることができませんでした。 –

+0

Excelent説明! –

0

親プロセスはp.Start()を呼び出すものです。私はあなたのアプリケーション(発信者)だと思います。 子プロセスはpです。つまり、呼び出し先です。要するに