ProcessStartInfo挂在“ WaitForExit”上吗?为什么?

我有以下代码:

info = new System.Diagnostics.ProcessStartInfo("TheProgram.exe", String.Join(" ", args));

info.CreateNoWindow = true;

info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

info.RedirectStandardOutput = true;

info.UseShellExecute = false;

System.Diagnostics.Process p = System.Diagnostics.Process.Start(info);

p.WaitForExit();

Console.WriteLine(p.StandardOutput.ReadToEnd()); //need the StandardOutput contents

我知道我正在启动的进程的输出大约7MB长。在Windows控制台中运行它可以正常工作。不幸的是,它以编程方式无限期地挂在WaitForExit上。还要注意,对于较小的输出(如3KB),此代码不会挂起。

ProcessStartInfo中的内部StandardOutput是否可能无法缓冲7MB?如果是这样,我该怎么办?如果没有,我在做什么错?

回答:

问题是如果您重定向StandardOutput和/或StandardError内部缓冲区可能已满。无论您使用什么顺序,都可能出现问题:

  • 如果您在读取StandardOutput过程之前等待该过程退出,则该过程可能会阻止尝试对其进行写入,因此该过程永远不会结束。
  • 如果从阅读StandardOutput使用ReadToEnd的,然后 你的 过程可以阻止如果过程永远不会关闭StandardOutput(例如,如果它永远不会终止,或者如果它被阻止写入StandardError)。

解决方案是使用异步读取来确保缓冲区未满。为了避免任何死锁并收集两者的所有输出StandardOutputStandardError您可以执行以下操作:

编辑:请参阅下面的答案,以了解如果发生超时,如何避免 。

using (Process process = new Process())

{

process.StartInfo.FileName = filename;

process.StartInfo.Arguments = arguments;

process.StartInfo.UseShellExecute = false;

process.StartInfo.RedirectStandardOutput = true;

process.StartInfo.RedirectStandardError = true;

StringBuilder output = new StringBuilder();

StringBuilder error = new StringBuilder();

using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))

using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))

{

process.OutputDataReceived += (sender, e) => {

if (e.Data == null)

{

outputWaitHandle.Set();

}

else

{

output.AppendLine(e.Data);

}

};

process.ErrorDataReceived += (sender, e) =>

{

if (e.Data == null)

{

errorWaitHandle.Set();

}

else

{

error.AppendLine(e.Data);

}

};

process.Start();

process.BeginOutputReadLine();

process.BeginErrorReadLine();

if (process.WaitForExit(timeout) &&

outputWaitHandle.WaitOne(timeout) &&

errorWaitHandle.WaitOne(timeout))

{

// Process completed. Check process.ExitCode here.

}

else

{

// Timed out.

}

}

}

以上是 ProcessStartInfo挂在“ WaitForExit”上吗?为什么? 的全部内容, 来源链接: utcz.com/qa/399060.html

回到顶部