gpt4 book ai didi

c# - ProcessStartInfo 卡在 "WaitForExit"上?为什么?

转载 作者:行者123 更新时间:2023-12-02 04:44:58 26 4
gpt4 key购买 nike

我有以下代码:

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 之前等待进程退出,该进程可能会阻止写入它,因此该进程永远不会结束。
  • 如果您使用 ReadToEnd 从 StandardOutput 读取数据,那么如果进程永远不会关闭 StandardOutput(例如,如果它永远不会终止,的进程可能会阻塞,或者如果写入StandardError被阻止)。

解决方案是使用异步读取来确保缓冲区不会变满。为了避免任何死锁并收集 StandardOutputStandardError 的所有输出,您可以这样做:

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

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.
}
}
}

关于c# - ProcessStartInfo 卡在 "WaitForExit"上?为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56491276/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com