如何正确读取c#进程标准错误流而不会出现死锁?

gor*_*ous 2 c# .net-core

根据MSDN ,我真的觉得我正在遵循最佳实践。但我最有可能失去了一些东西,因为从该行继续后,我的代码,挂起:string errorOutput = cmd.StandardError.ReadToEnd();。我究竟做错了什么?

        var batchfile = File.OpenWrite("run.bat");
        StreamWriter writer = new StreamWriter(batchfile);
        writer.Write("dotnet run" + '\n');
        //writer.Write("set /p temp=\"Hit enter to continue\"" + '\n');
        writer.Close();

        var cmd = new Process();
        cmd.StartInfo.FileName = batchfile.Name;
        cmd.StartInfo.UseShellExecute = false;
        cmd.StartInfo.RedirectStandardError = true;

        cmd.Start();
        string errorOutput = cmd.StandardError.ReadToEnd();
        cmd.WaitForExit();

        var outputfile = File.OpenWrite("run_errorOut.txt");
        StreamWriter outputWriter = new StreamWriter(outputfile);
        outputWriter.Write(errorOutput);
        outputWriter.Close();
Run Code Online (Sandbox Code Playgroud)

如果有帮助:目前此代码正在 dotnetcore2.2 应用程序内的 xunit 测试中运行(其目标框架是“netcoreapp2.2”)。

Min*_*ica 5

所以不久前我遇到了一个非常相似的问题,几乎完全相同,我发现的是:

  • 尝试读取 StandardError/Output 而没有任何东西可读取块,直到有可读取的东西(或死锁,如果没有写入任何东西 - 例如进程已退出)
  • cmd.HasExited 在读取标准错误/输出之前为假,因此无法用于检测何时完成(然后读取标准错误/输出)

我发现最可靠的方法是使用提供的事件Process

var outData = new StringBuilder();
var errData = new StringBuilder();    

cmd.OutputDataReceived += (sender, args) => outData.Append(args.Data ?? string.Empty);
cmd.ErrorDataReceived += (sender, args) => errData.Append(args.Data ?? string.Empty);
Run Code Online (Sandbox Code Playgroud)

然后之后cmd.Start() == true

cmd.BeginErrorReadLine();
cmd.BeginOutputReadLine();
Run Code Online (Sandbox Code Playgroud)

启动事件触发。

进程退出后,您可以调用.ToString()StringBuilders 来获取数据:

Console.WriteLine(outData.ToString());
Console.WriteLine(errData.ToString());
Run Code Online (Sandbox Code Playgroud)

(注意.ToString()使用时可以隐式Console.WriteLine

  • 有时在调试时,直接在事件处理程序中 Debug 或 Console.WriteLine 也很有用,而不是在 StringBuilder 中累积输出。这样,如果你的主线程在 process.WaitForExit() 上被阻塞,你仍然可以检查输出,也许会看到为什么子进程卡住了。你经常看到类似````覆盖文件吗?(Y/N):```` 在输出中,可以直观地知道为什么卡住了。 (2认同)