out /错误缓冲区死锁

时间:2011-10-31 21:48:16

标签: c# .net

以下是代码:

var output = new StringWriter();
var error = new StringWriter();

var p = new Process();
p.StartInfo = new ProcessStartInfo
{
    WorkingDirectory = workingDir,
    FileName = file,
    Arguments = args,
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
};
p.OutputDataReceived += (o, e) => { output.WriteLine(e.Data); };
p.ErrorDataReceived += (o, e) => { error.WriteLine(e.Data); };

p.Start();

if (!p.WaitForExit((int)timeout.TotalMilliseconds))
{
    p.Kill();
    throw new Exception("Timeout expired.");
}

string errorData = error.ToString();
if (errorData.Length > 0)
    throw new Exception(errorData);

return output.ToString();

我希望只要数据可用就会调用OutputDataReceivedErrorDataReceived个处理程序,但这种情况不会发生。对于将大量内容输出到stdout的进程,此代码最终会在throw new Exception("Timeout expired.");上退出。我尝试将一些调试代码抛入处理程序,但它永远不会被调用。指定out / err处理程序的全部意义是不是异步调用它们?

2 个答案:

答案 0 :(得分:4)

来自the docs

  

在StandardOutput上的异步读取操作期间启用该事件。要启动异步读取操作,必须重定向Process的StandardOutput流,将事件处理程序添加到OutputDataReceived事件,并调用BeginOutputReadLine 。此后,每次进程将一行写入重定向的StandardOutput流时,OutputDataReceived事件都会发出信号,直到进程退出或调用CancelOutputRead。

您没有执行任何异步读取,因此不会触发该事件。

如果你只是在启动过程后添加对p.BeginOutputReadline()的调用,它就会起作用。同样,要读取错误流,请调用BeginErrorReadLine()

答案 1 :(得分:1)

要开始接收标准输出和标准错误的事件,您需要分别拨打BeginOutputReadLine()BeginErrorReadLine()