I have a System.Diagnostics.Process object in a program targeted at the .Net framework 3.5
I have redirected both StandardOutput
and StandardError
pipes and I'm receiving data from them asynchronously. I've also set an event handler for the Exited event.
Once I call Process.Start()
I want to go off and do other work whilst I wait for events to be raised.
Unfortunately it appears that, for a process which returns a large amount of information, the Exited event is fired before the last OutputDataReceived
event.
How do I know when the last OutputDataReceived
has been received? Ideally I would like the Exited
event to be the last event I receive.
Here is an example program:
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);
}
}
}
When running this program you will notice that "Exited (Event)" appears in a completely variable location within the output. You may need to run it a few times and, obviously, you will need to replace "output.exe" with a program of your choice that produces a suitably large amount of output.
So, the question again: How do I know when the last OutputDataReceived
has been received? Ideally I would like the Exited
event to be the last event I receive.
The answer to this is that e.Data
will be set to null
:
static void proc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if( e.Data == null ) _exited.Set();
}