Runtime: NetworkStream.ReadAsync/WriteAsync ignores CancellationToken

Created on 10 Jan 2017  路  8Comments  路  Source: dotnet/runtime

I'm looking at this commit from @stephentoub and I see the CancellationToken is not used once the BeginRead/Write operation is started. Especially for the read scenario it makes sense to be able to stop the reading and continue working. Or am I missing something?

Most helpful comment

@baal2000 That works if you can then close the Socket. But if you need to keep it opened it's a problem, because the read will be still hanging there, potentially colliding with next read(s).

All 8 comments

Or am I missing something?

These NetworkStream.Read/WriteAsync implementations are just wrappers around the underlying NetworkStream.Begin/EndRead/Write methods, which are in turn just wrappers around the underlying Socket.Begin/EndReceive/Send methods, which do not support cancellation. I agree that cancellation would be useful, but adding it can't be done unless/until cancellation is supported at the sockets level, and it's not currently.

Ahh, I completely forgot about the underlying Socket. Thanks.

@cincuranet
@stephentoub

I suggest awaiting on a composite task Task.WhenAny that combines NetworkStream.Read/WriteAsync task with another "monitor" Task (for instance, Task.Delay(timeout, token) or TaskCompletionSource-based task). The "monitor" Task can be interrupted by cancelling or by timing out . When the composite Task completes due to "monitor" Task completion, the NetworkStream and the underlying Socket can be closed and the whole network interaction stopped as if Read/WriteAsync did implement cancellation/timeout natively.

@baal2000, yes, a consumer of the APIs could choose to do that: https://blogs.msdn.microsoft.com/pfxteam/2012/10/05/how-do-i-cancel-non-cancelable-async-operations/. But we wouldn't want to do that in the implementation of NetworkStream itself.

@baal2000 That works if you can then close the Socket. But if you need to keep it opened it's a problem, because the read will be still hanging there, potentially colliding with next read(s).

@cincuranet Agree this would not provide solution if the stream/socket was to be kept open. Still, might be a good idea to use the monitor Task approach in select scenarios to protect yourself from the upstream code potentially hanging indefinitely on awaiting ReadAsync/WriteAsync.

@stephentoub Thanks for your input. Agree this should not be part of NetworkStream.

Is there a workaround to this issue in case the Socket needs to be kept open?

My trick is periodically checking stream.DataAvailable. Is a good way to do this?

while (!stream.DataAvailable)
{
    await Task.Delay(100, cancel);
}

Is there a workaround to this issue in case the Socket needs to be kept open?

Not really. Once https://github.com/dotnet/corefx/issues/24430 is implemented, then the support on NetworkStream will "just work".

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chunseoklee picture chunseoklee  路  3Comments

v0l picture v0l  路  3Comments

omariom picture omariom  路  3Comments

jzabroski picture jzabroski  路  3Comments

EgorBo picture EgorBo  路  3Comments