Asynchronous read synchronization from stdout of a child process

I have an application that launches a sub process and asynchronously processes its stdout . The problem is that the async operation takes some time, and I want the method responsible for executing the process to finish after all async IO operations are executed.

I have a code like this:

 using System.Diagnostics; Process process = new Process(); // ... process.OutputDataReceived += new DataReceivedEventHandler(this.OnRecvStdOut); process.ErrorDataReceived += new DataReceivedEventHandler(this.OnRecvStdErr); // ... process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); // ... process.WaitForExit(); 

Now I am looking for a way that a program should wait for all I / O to complete ( OnRecvStdOut ).

I’m at least talking about using one of the System.Threading classes, but I'm not sure which class is the best for this and how to do it in the end, the best way would probably be this:

 public void OnRecvStdOut(...) { something.Increase(); // the stuff that takes so long something.DecreaseAndSignal(); } 

And in the main function:

 something.WaitUntilZero(); 

Note. I would like to allow parallel processing of both StdErr and stdout . Something cannot rely on Wait be called as Signal , because the Increase() and DecreaseAndSignal() pairs will be called many times before Wait appears.

The second thing that came to mind was that it could signal many times (without the need for signal processing) and use a loop in the main function, for example:

 while( ioOperations > 0){ something.WaitForSignal(500); } 

Edit: current working solution:

I came up with what seems to work:

 using System.Threading; protected int IOCount = 0; protected AutoResetEvent _IOSyncEvent = new AutoResetEvent(false); public void OnRecvStdOut(...) { Interlocked.Increase( ref IOCount); // the stuff that takes so long Interlocked.Decrease( ref IOCount); IOSyncEvent.Set(); } // After process.WaitForExit() while( IOCount > 0){ // 250 for a case that signal occurs after condition and before wait IOSyncEvent.WaitOne(250); } 

But I would appreciate any comments on how to make this a “good practice path” or what are the possible implementation risks, despite this.

+4
source share
1 answer

Use the CountdownEvent parameter of 2. Each callback received using the data checks the x.EndOfStream flag (where x is the standard dump or standard protection of the process object). If EOF, then the signal is countdownevent. It will work because both standard and output error streams will ultimately signal an event. As soon as both transmit a signal, the wait on it will return. It is also a very effective way to do this.

+1
source

Source: https://habr.com/ru/post/1442719/


All Articles