的ProcessStartInfo挂在" WaitForExit"?为什么? [英] ProcessStartInfo hanging on "WaitForExit"? Why?
问题描述
我有以下的code:
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。另请注意,这并不code不挂较小的输出(如3KB)。
I know that the output from the process I am starting is around 7MB long. Running it in the Windows console works fine. Unfortunately programmatically this hangs indefinitely at WaitForExit. Note also this does code NOT hang for smaller outputs (like 3KB).
是否有可能在的ProcessStartInfo内部StandardOutput不能缓冲7MB?如果是这样,我应该怎么办呢?如果不是这样,我是什么做错了吗?
Is it possible that the internal StandardOutput in ProcessStartInfo can't buffer 7MB? If so, what should I do instead? If not, what am I doing wrong?
推荐答案
的问题是,如果您重定向 StandardOutput
和/或 StandardError的
内部缓冲区已满。无论您使用的命令,可以有一个问题:
The problem is that if you redirect StandardOutput
and/or StandardError
the internal buffer can become full. Whatever order you use, there can be a problem:
- 如果您等待的过程中阅读之前退出
StandardOutput
的过程中可以阻止试图写它,所以这个过程永远不会结束。 - 如果您从
StandardOutput
读取使用ReadToEnd的那么的您的过程中可以阻止如果进程永远不会关闭StandardOutput
(例如,如果它永远不会终止,或者如果它被阻止写入StandardError的
)。
- If you wait for the process to exit before reading
StandardOutput
the process can block trying to write to it, so the process never ends. - If you read from
StandardOutput
using ReadToEnd then your process can block if the process never closesStandardOutput
(for example if it never terminates, or if it is blocked writing toStandardError
).
的解决方案是使用异步读取,以确保缓冲区没有得到充分。为了避免任何死锁和收集来自所有输出都 StandardOutput
和 StandardError的
你可以这样做:
The solution is to use asynchronous reads to ensure that the buffer doesn't get full. To avoid any deadlocks and collect up all output from both StandardOutput
and StandardError
you can do this:
编辑:请参阅以下处理超时的答案,避免 ObjectDisposeException 例外
See answers below for to handle the timeout and avoid ObjectDisposeException exceptions.
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"?为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!