StreamReader.Read blocking?

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I realise this sounds a bit strange, but it appears that StreamReader.Read is
blocking. I have redirected stdin, out and err of a particular process, and I
spawn threads that handle the reading of the streams by placing the stream
data into a local buffer.

The problem I am encountering is trying to stop the threads when I want to
dispose of the class instance. The StopStandardOutputThread method locks on
the call to standardOutputReader.Join() preventing the class from disposing.
Here are the main suspects:

private void ReadStandardOutput()
{
Debug.WriteLine("Started reading standard output.");
char [] buffer = null;
while(true)
{
if (stopOutputReader.WaitOne(5, false))
break;

if (standardOutput != null)
{
buffer = new char[255];
if (standardOutput.Read(buffer, 0, buffer.Length) > 0)
rawBuffer += new String(buffer);
}
}
Debug.WriteLine("Stopped reading standard output.");
}

private void StopStandardOutputThread()
{
Debug.WriteLine("Stopping standard output thread...");
stopOutputReader.Set();
standardOutputReader.Join();
Debug.WriteLine("Standard output thread stopped.");
}

I commented out the code that does the work of reading the stream and
placing the result in the buffer, and everything worked as expected. A bit
more Debug.WriteLine-ing narrowed the problem down to the call to
standardOutput.Read(). It appears to block on this call, waiting for data
from the stream.

About the Read() method, MSDN says: This method returns after either count
characters are read, or the end of the file is reached. (It's in the remarks
section.) This is where I get shot in the foot. Because the stream is open
the entire time, it never reaches EOF, and while there is no data in the
stream, it can't read buffer.Length characters from it, so it's sitting there
waiting for action. Doesn't this make Read() a blocking method? If so, what's
the point of ReadBlock()?

About ReadBlock(), MSDN says: The method blocks until either count
characters are read, or all characters have been read.

Now that I'm re-reading that line, I believe I have answered my own
question. I should perhaps use ReadBlock()? I'm reading that line as meaning,
if you call ReadBlock() on an empty stream, it will return with no data read.
Does this seem logical? I'm going to try it now.

Anyway, the work around I'm trying (prior to ReadBlock) is to modify the
stop method to look like this:

private void StopStandardOutputThread()
{
Debug.WriteLine("Stopping standard output thread...");
stopOutputReader.Set();
if (!standardOutputReader.Join(250))
standardOutputReader.Abort();
Debug.WriteLine("Standard output thread stopped.");
}

Which I don't like, as I like threads to end under their own steam.

If anyone can shed some light on this, it would be much appreciated.

Thanks,

Geoff.
 
As a follow up: ReadBlock() didn't make any difference, but the
Join(250)->Abort()->Join() is working.

I'm at a loss to explain the difference between Read() and ReadBlock(). They
appear to work exactly the same in this scenario.
 
Back
Top