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

我有以下代码:

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的所有输出,可以执行以下操作:

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

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

如何在Gulp中使用stdout和stderr child_process - python

我将gulp与python flask一起使用。var gulp = require('gulp'); var spawn = require('child_process').spawn; var app = spawn('python', ['app.py']); gulp.…

为应用程序池“ xxx”提供服务的进程与Windows Process Activation Service发生致命通信错误 - c#

在软件更新之后,收到多个此类错误后,应用程序池停止了两次:为应用程序池“ xxx”提供服务的进程在Windows进程激活服务中遇到致命的通信错误。进程ID为“ yyy”。数据字段包含错误号。事件ID:5011错误代码:0x6D000780对最新版本的软件更改很小,无法解释此问题(只是存储过程中的一个新字段),但是我无法还原旧版本以检查是否存在问题。我有相同的…

LeetCode题解计算机为什么是基于二进制的?

可以是三进制么?二进制有什么好处?题解:为什么叫电子计算机?算盘应该没有二进制

LeetCode题解统计城市的所有灯泡

这个是我刚毕业的时候,一个真实的面试题,这是一个开放题。题目描述:想办法,将一个城市的所有灯泡数量统计出来。题解:费米估算法1、如果某个城市常驻人口有1000万2、假设每5人居住在一套房里,每套房有灯泡5只,那么住宅灯泡共有1000万只3、假设公众场所每10人共享一只灯泡,那么共有100万只4、主要的这两者相加就得出了1100万只当然实际上这是估算的,具体应…

LeetCode题解黑白圆盘

一个圆盘被涂上了黑白二色,两种颜色各占一个半圆。圆盘以一个未知的速度、按一个未知的方向旋转。你有一种特殊的相机可以让你即时观察到圆上的一个点的颜色。你需要多少个相机才能确定圆盘旋转的方向?题解:可以用一个相机即可