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?
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".
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).