为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
鸿蒙传说 2019-06-21 15:04:38
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?如果是的话,我应该做些什么呢?如果没有,我做错了什么?
查看完整描述

3 回答

?
HUH函数

TA贡献1836条经验 获得超4个赞

问题是如果你重定向StandardOutput和/或StandardError内部缓冲区可能会满。不管你用什么命令,都会有问题:

  • 如果在读取之前等待进程退出

    StandardOutput

    进程可以阻止试图写入它,因此进程永远不会结束。
  • 如果你读到

    StandardOutput

    然后使用ReadToEnd

    你的

    如果进程从未关闭,则进程可以阻塞。

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


查看完整回答
反对 回复 2019-06-21
?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

我只想添加以下内容:在释放outputWaitHandle和ErrorWaitHandle之前,需要移除OutputDataReciser和ErrorDataReces委托。如果进程在超时之后继续输出数据,然后终止,则在释放后将访问outputWaitHandle和errorWaitHandle变量。


查看完整回答
反对 回复 2019-06-21
  • 3 回答
  • 0 关注
  • 1099 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信