异步读取过程输出时延迟

我使用.NET和C#来启动进程并异步读取它的输出。 我的问题是在我的程序读取输出之前似乎有一段延迟。 如果我在命令行上运行可执行文件,它会在开始运行时立即输出。 但是当我使用我的代码运行它时,在Process退出之前不会调用ReadOutput事件处理程序。 我想用它来提供进程输出的实时视图,所以我不想等待(几分钟)直到进程退出。

这是一些相关的代码:

MyProcess = new Process(); MyProcess.StartInfo.FileName = command; MyProcess.StartInfo.Arguments = args; MyProcess.StartInfo.UseShellExecute = false; MyProcess.StartInfo.RedirectStandardOutput = true; MyProcess.StartInfo.RedirectStandardError = true; MyProcess.StartInfo.RedirectStandardInput = true; MyProcess.OutputDataReceived += new DataReceivedEventHandler(ReadOutput); MyProcess.ErrorDataReceived += new DataReceivedEventHandler(ReadOutput); if (!MyProcess.Start()) { throw new Exception("Process could not be started"); } try { MyProcess.BeginOutputReadLine(); MyProcess.BeginErrorReadLine(); } catch (Exception ex) { throw new Exception("Unable to begin asynchronous reading from process"; } 

这是我的事件处理程序:

 private void ReadOutput(object sendingProcess, DataReceivedEventArgs outLine) { OutputBuilder.AppendLine(outLine.Data); Console.WriteLine(outLine.Data); Console.Out.Flush(); } 

根据我使用lambda语法的注释,这就是我这样做的方式(C#3)。

  ///  /// Collects standard output text from the launched program. ///  private static readonly StringBuilder outputText = new StringBuilder(); ///  /// Collects standard error text from the launched program. ///  private static readonly StringBuilder errorText = new StringBuilder(); ///  /// The program's entry point. ///  /// The command-line arguments. /// The exit code. private static int Main(string[] args) { using (var process = Process.Start(new ProcessStartInfo( "program.exe", args) { CreateNoWindow = true, ErrorDialog = false, RedirectStandardError = true, RedirectStandardOutput = true, UseShellExecute = false })) { process.OutputDataReceived += (sendingProcess, outLine) => outputText.AppendLine(outLine.Data); process.ErrorDataReceived += (sendingProcess, errorLine) => errorText.AppendLine(errorLine.Data); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); Console.WriteLine(errorText.ToString()); Console.WriteLine(outputText.ToString()); return process.ExitCode; } 

您的方法中的问题可能是该进程仅在退出时完成一行的输出。 没有办法控制异步事件处理程序何时触发。

在控制台应用程序中,最好的办法是定期检查新输出并同步读取和显示:

  while (!p.HasExited) { if (!p.StandardOutput.EndOfStream) { errorBuilder.Append(p.StandardError.ReadToEnd()); outputBuilder.Append(p.StandardOutput.ReadToEnd()); Console.Write(p.StandardOutput); } else { Thread.Sleep(200); } } 

在UI项目中,您分别使用TimerDispatcherTimer for WinForms和WPF来调用循环的内容并更新UI。

请注意,我不会刷新Console.Out ,因为Console.Write()Console.WriteLine()会自动导致这种情况。

尝试添加MyProcess.WaitForExit方法调用:

 MyProcess.BeginOutputReadLine(); MyProcess.BeginErrorReadLine(); // will wait for the associated process to exit MyProcess.WaitForExit();