I've seen something similar in a small program I created to run several instances of SysInternals sdelete.exe and collect their standard output.
I'll explain my situation so that you can determine if it's relevant to yours.
Each Process instance was created in a separate thread and the relevant part of the code was this fairly standard stuff:
Process p = new Process();
p.StartInfo = psi;
p.Start();
String result = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Occasionally TaskManager would show that a child process had ended but the corresponding ReadToEnd would block until one of the other longer running child processes ended. Something odd was going on as obviously that could not happen! I could show that the problem was nothing to do with sdelete.exe and came to the conclusion that the Process.Start method is not thread safe. Specifically if the execution of the Start method on different threads overlaps there will be a coupling between the processes' redirected output streams.
The solution was simply to prevent overlapping calls to Process.Start with lock object shared between all the threads. With this modification in place the processes no longer exhibited the strange coupling behaviour.
Process p = new Process();
p.StartInfo = psi;
lock (startLock) {
p.Start();
}
String result = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Let me know if that's of any help.
Some other comments on your code, not that you asked, but it's useful to know stuff.
The output streams may deliver data after WaitForExit has returned making it unsafe to assume that you have all the data at that point. It also makes it very difficult to know when to call the Process.Dispose method. The solution is not to proceed until both output streams have returned null, the indicator that they have closed, i.e.
DataReceivedEventArgs.Data == null
.
Incidentally your DataReceived event handlers are discarding blank lines. This may be what you want but do be aware that
args.Data == String.Empty
is perfectly normal and means a blank line was written to the output stream. On the other hand
args.Data == null
occurs once only when the stream has closed.
Alan.