的ProcessStartInfo挂在" WaitForExit"?为什么? [英] ProcessStartInfo hanging on "WaitForExit"? Why?

查看:353
本文介绍了的ProcessStartInfo挂在" WaitForExit"?为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的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 closes StandardOutput (for example if it never terminates, or if it is blocked writing to StandardError).

的解决方案是使用异步读取,以确保缓冲区没有得到充分。为了避免任何死锁和收集​​来自所有输出都 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆