从C#通过Process类生成时,正确处理程序的标准错误和输出的方法?

时间:2010-11-09 18:54:51

标签: .net process subprocess redirectstandardoutput waitforexit

我阅读了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内容。

那是正确的方法吗?

2 个答案:

答案 0 :(得分:7)

您的示例代码可能导致死锁,其中有一些内容写入StandardOutput而不是StandardError。您链接的文档中的下一个示例说明了这一点。

基本上,我建议使用两个流上的异步读取来在写入Streams时填充缓冲区,然后调用WaitForExit

答案 1 :(得分:3)

问题出现是因为子进程将其标准输出和标准错误写入一对管道,这些管道由OS提供有限的缓冲区。如果父母没有积极阅读他们两个,那么他们就有可能填满。当管道填满时,对其的任何后续写入都将被阻止。

在您的示例中,您正在阅读所有StandardError,然后阅读StandardOutput的所有内容。如果子进程只将一小部分数据写入StandardError和/或StandardOutput,则此工作正常。如果子进程想要将大量数据写入StandardOutput,则会出现问题。当父进程正在等待使用StandardError中的数据时,子进程正忙于填充StandardOutput缓冲区。

最安全的方法是同时读取标准输入和标准错误。有几种方法可以做到这一点:

  • 产生单独的线程并在每个
  • 上调用ReadToEnd
  • 在一个帖子上使用BeginReadEndRead
  • Process.ErrorDataReceivedProcess.OutputDataReceived个活动中添加处理程序,然后致电Process.BeginErrorReadLineProcess.BeginOutputReadLine