I have a StreamReader
and I want to know if there is data available without blocking the thread.
I tried the Peek
method but it blocks when there is no data available.
using (StreamReader reader = new StreamReader(stream))
{
if (reader.Peek() == -1) // Blocks here while there is no data and unblocks as soon as there is data.
{
}
}
If I check the mono code of the Peek() method, it says in comment
//
// Peek can block:
// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=96484
//
Unfortunately, the link doesn't work anymore.
I found here, here, here and here that Microsoft seems to have a bug that cause Peek
to block. But all these posts are pretty old. I think mono deliberately made Peek()
blocking because of this bug.
So I have two questions
Peek()
to block? If no, mono should change its implementation of Peek()
to be non-blocking.OK, let me just say that I don't really know what you are trying to accomplish here. However, from what I can see, the Peek
method has to block the current thread in order to work. This is what the documentation says:
The Peek method returns an integer value in order to determine whether the end of the file, or another error has occurred. This allows a user to first check if the returned value is -1 before casting it to a Char type.
So, Peek
should only return -1 if it encounters an error or end of the file. This is a little confusing, because there may be no file involved. The stream might be a response from a WebRequest
, in which case, the part of the stream that you're trying to read might not be downloaded yet. So, Peek
has to wait until it's done because, and this is not clear from the documentation, it returns the first byte read from the stream.
The problems that are mentioned in the links you posted are concerned with multiple threads using the same StreamReader
, which is not your case. I also believe that there used to be a bug that would cause one StreamReader
waiting for input to block another, but I believe it has since been fixed. I'm not sure what the Mono implementation does.
To answer your question, to do this without blocking the thread, I would try the following:
ReadAsync
and then await
or ContinueWith
on the task to make it non-blocking.However, as was correctly remarked in the comments, if you put the whole thing into another thread, do you really need Peek
? Why not just put it into your typical while (Read(...)) { ... }
block and process the data as it's coming?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With