从过程的空的stdout原因同步读数据死锁[重复](Synchronized reading dat

2019-10-29 15:33发布

这个问题已经在这里有一个答案:

  • 从进程读取,StreamReader.Peek()工作不正常 1个回答

我无法建立,创建和使用Python进程交互C#应用程序1 。 一个简单的例子在下面给出。

编辑:在SO进一步研究亮相,我的问题是,可能重复。 .NET Framework中的一个潜在相关的已知错误是duscussed 这里和这里 。 看来,早在2014年只有简单的解决办法的确是问孩子的过程写在标准输出和标准错误的东西。 但是,我想知道,如果这个假设是正确的,不知道是否有尚未从2014年起一直是修复?

我必须满足下列边界条件:

  1. 我不能交给一个脚本或命令后关闭蟒蛇的过程,但我必须保持过程活着。 编辑:出于这个原因,我不能利用Process.WaitForExit()方法
  2. 由于性病的继续开放所有的时间,我相信我能不能检查EndOfStream,因为这将需要阅读的数据流,不存在结束。
  3. 此外,我的应用程序必须等待蟒蛇过程的反应,因此使用BeginOutputReadLine()与OnOutputDataReceived异步的选择似乎并不适合我。
  4. 为将被发送到蟒的命令是任意的用户输入,蟒结果可能是要么在stdout或stderr(“4 + 7”的结果为“11”存储在STDOUT;在“名称“4 +一个”结果‘A’未在STDERR定义”)

我做的是:

  • 设置在交互模式下一个python处理(参数“-i”)
  • 使标准输入,输出和错误的重定向
  • 启动过程
  • 得到该标准的StreamReaders和作家

在那之后,我要开始检查输出和错误。 我知道蟒蛇下面的一段信息写入STDERR

蟒2.7.11(v2.7.11:6d1b6a68f775,2015年12月5日,二十时32分19秒)[MSC v.1500 32位(英特尔)]在Win32

而我能够通过使用errorReader.Peek得到这条线(),并从errorReader读基于字符2 。

然而,与另一个进程的情况可能会完全不同。 即使与Python,我碰到以下问题:当我想首先从outputReader读,有包含在它和outputReader.Peek()似乎碰上了僵局罢了。 如上所述,这同样适用于outputReader.EndOfStream或outputReader.ReadToEnd()。 所以,我怎么知道,如果标准输出可以在所有使用而不会导致死锁?

码:

        // create the python process StartupInfo object
        ProcessStartInfo _tempProcessStartInfo = new ProcessStartInfo(@"C:\TMP\Python27\python.exe");
        // ProcessStartInfo _tempProcessStartInfo = new ProcessStartInfo(PathToPython + "python.exe");

        // python uses "-i" to run in interactive mode
        _tempProcessStartInfo.Arguments = "-i";

        // Only start the python process, but don't show a (console) window
        _tempProcessStartInfo.WindowStyle = ProcessWindowStyle.Minimized;
        _tempProcessStartInfo.CreateNoWindow = true;


        // Enable the redirection of python process std's
        _tempProcessStartInfo.UseShellExecute = false;

        _tempProcessStartInfo.RedirectStandardOutput = true;
        _tempProcessStartInfo.RedirectStandardInput = true;
        _tempProcessStartInfo.RedirectStandardError = true;

        // Create the python process object and apply the startupInfos from above
        Process _tempProcess = new Process();
        _tempProcess.StartInfo = _tempProcessStartInfo;

        // Start the process
        bool _hasStarted = _tempProcess.Start();

        //// ASynch reading seems not appropriate to me:
        // _tempProcess.BeginOutputReadLine();
        // _tempProcess.BeginErrorReadLine();

        // Create StreamReaders and Writers for the Std's
        StreamReader outputReader = _tempProcess.StandardOutput;
        StreamReader errorReader = _tempProcess.StandardError;
        StreamWriter commandWriter = _tempProcess.StandardInput;

        // Create StringBuilder that collects results and ErrorMessages
        StringBuilder tmp = new StringBuilder("");

        // Create temp variable that is used to peek into streams. C# uses -1 to indicate that there is no more byte to read
        int currentPeek = -1;

        // Get Initial Error Message. In this specific case, this is the python version
        tmp.AppendLine("INITIAL ERROR MESSAGE:");
        currentPeek = errorReader.Peek();
        while (currentPeek >= 0)
        {
            char text = (char)errorReader.Read();
            tmp.Append(text);
            currentPeek = errorReader.Peek();
        }

        // Get initial output Message. In this specific case, this is EMPTY, which seems to cause this problem, as ...
        tmp.AppendLine("INITIAL STDOUT MESSAGE:");

        //// ... the following command CREATES a well defined output, and afterwards everything works fine (?) but ...
        //commandWriter.WriteLine(@"print 'Hello World'");

        //// ... without the the above command, neither
        //bool isEndOfStream = outputReader.EndOfStream;
        //// ... nor
        // currentPeek = outputReader.Peek();
        //// ... nor
        // tmp.AppendLine(outputReader.ReadLine());
        //// ... nor 
        //tmp.AppendLine(outputReader.ReadToEnd());
        //// ... works

        // Therefore, the following command creates a deadlock
        currentPeek = outputReader.Peek();
        while (currentPeek >= 0)
        {

            char text = (char)outputReader.Read();
            tmp.Append(text);
            currentPeek = errorReader.Peek();
        }

        _currentPythonProcess = _tempProcess;
        return true;

1一个容易解决这一非常具体的问题是首先发送一个有效的命令的过程,例如简单的“4”,它返回一个“4”,以及...但是,我想了解如何处理流,管道和在corresponing读者和作家的作品以及我如何在C#中使用它们。 谁知道未来带来的,也许我遇到缓冲问题时,蟒蛇响应为2 ^ n + 1个字节长...... 2 ,我知道我还可以读取线为主。 然而,皮克()阻止我报告说,涉及截断线的问题。

Answer 1:

如果你能等待进程结束,然后读取缓冲区,您可能能够使用Process.WaitForExit 。 还有,你可以检查,另一种方法Process.WaitForInputIdle ,但要看有消息循环,我不认为一个过程Python执行脚本时得到。



文章来源: Synchronized reading data from Process's empty stdout causes deadlock [duplicate]
标签: c# ipc stdout peek