当最后一个OutputDataReceived已到达时,我该如何知道?

25

我在一个针对 .Net Framework 3.5 的程序中有一个 System.Diagnostics.Process 对象。

我已经重定向了 StandardOutputStandardError 管道,并异步地从它们接收数据。我还为 Exited 事件设置了一个事件处理程序。

一旦我调用 Process.Start(),我希望能够离开并在等待事件被引发的同时去做其他工作。

不幸的是,对于返回大量信息的进程,似乎在最后一个 OutputDataReceived 事件之前就会触发 Exited 事件。

如何知道最后一个 OutputDataReceived 已经被接收?理想情况下,我希望 Exited 事件是我接收到的最后一个事件。

以下是示例程序:

using System;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApplication1
{
  class Program
  {

    static void Main(string[] args)
    {
      string command = "output.exe";
      string arguments = " whatever";

      ProcessStartInfo info = new ProcessStartInfo(command, arguments);

      // Redirect the standard output of the process. 
      info.RedirectStandardOutput = true;
      info.RedirectStandardError = true;

      // Set UseShellExecute to false for redirection
      info.UseShellExecute = false;

      Process proc = new Process();
      proc.StartInfo = info;
      proc.EnableRaisingEvents = true;

      // Set our event handler to asynchronously read the sort output.
      proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived);
      proc.ErrorDataReceived += new DataReceivedEventHandler(proc_ErrorDataReceived);
      proc.Exited += new EventHandler(proc_Exited);

      proc.Start();
      // Start the asynchronous read of the sort output stream. Note this line!
      proc.BeginOutputReadLine();
      proc.BeginErrorReadLine();

      proc.WaitForExit();

      Console.WriteLine("Exited (Main)");

    }

    static void proc_Exited(object sender, EventArgs e)
    {

      Console.WriteLine("Exited (Event)");
    }



    static void proc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
      Console.WriteLine("Error: {0}", e.Data);
    }



    static void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
      Console.WriteLine("Output data: {0}", e.Data);
    }


  }
}

运行此程序时,您会注意到"Exited (Event)"出现在输出的完全可变位置。 您可能需要运行几次,并且显然需要用生成足够大量输出的自选程序替换"output.exe"。

因此,问题再次出现:如何知道最后一个OutputDataReceived已被接收?理想情况下,我希望Exited事件是我接收到的最后一个事件。

2个回答

30
答案是这样的:

答案是e.Data将被设置为null

static void proc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
     if( e.Data == null ) _exited.Set();
}

_exited是什么意思? - undefined
@sdbbs _exited 可能是一个 AutoResetEvent。真不敢相信我们竟然在这个帖子14年后同时出现在这里。 - undefined

1
如果将 e.Data 设置为 null,会更加方便,但实际上,该值将是空字符串。请注意第一个值也可能是空字符串。真正的答案是一旦收到不为空的值,就寻找下一个空字符串。我正在使用 Visual Studio 2019。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接