2

I have an instance of network stream. When using ReadLineAsync no timeout exception is thrown. No problem with ReadLine. Why?

NetworkStream stream = GetStream();
stream.ReadTimeout = 1000; //1000ms
var reader = new StreamReader(stream, Encoding.UTF8, true, BufferSize, true);

so:

await reader.ReadLineAsync(); //no timeout error

but:

reader.ReadLine(); //timeout error.

What is going on?

Dmitry Pavlov
  • 30,789
  • 8
  • 97
  • 121
pwas
  • 3,225
  • 18
  • 40
  • 2
    @Igor `ReadLineAsync` in `StreamReader` doesn't not support cancellation token. – pwas Mar 08 '18 at 12:04
  • 1
    you can do something like this: https://stackoverflow.com/questions/28626575/can-i-cancel-streamreader-readlineasync-with-a-cancellationtoken – Darjan Bogdan Mar 08 '18 at 12:06
  • @DarjanBogdan yes, but even with this solution task is running underhood. I'd like to stop it. What's more it is strange that `ReadLine` reacts to timeout but `ReadLineAsync` not. – pwas Mar 08 '18 at 12:08
  • yes, unfortunately it seems it's not possible to achieve that with StreamReader – Darjan Bogdan Mar 08 '18 at 12:08
  • 1
    Because the async methods do not accept a CancellationToken the operation can't be cancelled (*due to a timeout or any other reason*). You will have to use a custom implementation of `StreamReaader` or use the `NetworkStream` directly. – Igor Mar 08 '18 at 12:09
  • 1
    Probably a dupe of this https://stackoverflow.com/questions/20131434/cancel-networkstream-readasync-using-tcplistener but not casting my Mjölnir close vote because of the dotnet core tag. – spender Mar 08 '18 at 12:29
  • @spender not sure - this Q seems to be questioning why ReadLineAsync does not adhere to `ReadTimeout` not so much how to cancel it with CancellationToken. – default Mar 08 '18 at 12:42
  • @Default yes, exactly. Finally, I will use workaround - cancel async operation with some tricky snippet and then close whole connection. But still, question is why `ReadLineAsync` doesn't respect `ReadTimeout` and `ReadLine` does. – pwas Mar 08 '18 at 12:44
  • 1
    @pwas you dont _have_ to use some tricky snippet - as Igor suggested, you can use the [NetworkStream.ReadAsync](https://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.readasync%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) directly. It *should* respect the ReadTimeout. – default Mar 08 '18 at 12:51

2 Answers2

0

I had a similar problem. I suppose that

await reader.ReadLineAsync();

is the same as

var ansTask = reader.ReadLineAsync();
ansTask.Wait(stream.ReadTimeout);

This means: Start a task async and then wait for it's completion for a while. Once you stopped waiting for it, you move on, but the asynchronous task will still try to complete.

If you are not happy that it didn't complete soon enough, you can add something like:

if (!readTask.IsCompleted) throw new TimeoutException();
0

I would guess that ReadLineAsync internally keeps reading in a loop until it finds an EOL, so even if the internal reads keep timing out, the loop will just try reading again until it gets an EOL.

Baruch
  • 20,590
  • 28
  • 126
  • 201