Async read from StandardOutput?

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
 
T

Tom Shelton

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.
 
B

Bob Altman

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top