Async read from StandardOutput?

  • Thread starter Thread starter Bob Altman
  • Start date Start date
B

Bob Altman

Hi all,

I'm trying to do something that is so fundamental I can believe it's as
difficult as it seems to be. I want to use the Process class to run a
program. When the program terminates, I want to return to my caller an
Int32 containing the completion code, a String containing the text written
to the StandardOutput stream, and a String containing the text written to
the StandardError stream.

The tricky part is that you can't just wait until the program completes and
then read from those streams. If the program writes a lot of text then it
will fill up the pipe and block waiting for someone to read the data from
the pipe. But the guy who will read from the pipe is blocked waiting for
the program to terminate, so you're deadlocked.

So (it seems to me) I have two choices: Either I can create a thread for
each stream and perform blocking ReadToEnd calls using the StreamReader
objects that my Process object gives me, or I can call BeginRead on the
BaseStream objects that I get from those StreamReader objects. The first
option ties up two extra threads for every program I start. The second
option is difficult to implement because Stream.BeginRead reads bytes, not
characters.

Any suggestions? This can't possibly be as difficult as I'm making it!

TIA - Bob
 
Hi all,

I'm trying to do something that is so fundamental I can believe it's as
difficult as it seems to be. I want to use the Process class to run a
program. When the program terminates, I want to return to my caller an
Int32 containing the completion code, a String containing the text written
to the StandardOutput stream, and a String containing the text written to
the StandardError stream.

The tricky part is that you can't just wait until the program completes and
then read from those streams. If the program writes a lot of text then it
will fill up the pipe and block waiting for someone to read the data from
the pipe. But the guy who will read from the pipe is blocked waiting for
the program to terminate, so you're deadlocked.

So (it seems to me) I have two choices: Either I can create a thread for
each stream and perform blocking ReadToEnd calls using the StreamReader
objects that my Process object gives me, or I can call BeginRead on the
BaseStream objects that I get from those StreamReader objects. The first
option ties up two extra threads for every program I start. The second
option is difficult to implement because Stream.BeginRead reads bytes, not
characters.

Converting byte arrays is farily simple - see the System.Text.Encoding class.

I personally would try the async io bit first.
 
Never mind... The Process object supports BeginOutputReadLine and
BeginErrorReadLine methods, with associated OutputDataReceived and
ErrorDataReceived events that do exactly what I'm trying to do. These must
be relatively new - I'm pretty sure they didn't exist in older versions of
the framework.

Bob
 
Back
Top