Task.Factory.FromAsync with CancellationTokenSource

前端 未结 3 1860
挽巷
挽巷 2020-12-31 07:32

I have the following line of code used to read asynchronously from a NetworkStream:

int bytesRead = await Task.Factory.FromAsync(this.stream.Begin         


        
3条回答
  •  失恋的感觉
    2020-12-31 07:57

    No, there is no generic way to cancel such a task. Cancellation is API specific.

    • For example, WebClient has a Cancel method.
    • A Socket or a FileStream needs to be Close'd to cancel an outstanding call.
    • Web-service clients have even different ways of aborting calls.
    • ...

    This is because the implementer of the IO operation must support cancellation.

    It might seem tempting to use NetworkStream.ReadAsync and pass a cancellation token but is Stream.ReadAsync. An the latter just throws away the token. Basically not supported.

    Stream.ReadAsync is just the base class method. It does not do anything by itself. Concrete IO operations are issued only by derived classed. Those must support cancellation natively. Stream can't do anything to force them. It happens that NetworkStream doesn't support cancellation.

    I understand that you want to cancel the operation and leave the socket open. But it is not possible. (Subjective note: This is really a sad state of affairs. Especially considering that Windows supports cancellable IO at the Win32 level.)

    If you still want your app to quickly continue, although the IO operation is not cancellable, just ignore the result of that task and continue. Be aware that eventually the IO might complete and for example drain data from the socket buffers or cause other side-effects.

    "Cancelling by ignoring" effectively make the stream position undefined. The stream becomes unusable. This doesn't really avoid the need to open a new stream. You still have to get rid of the old stream (in most cases) and reopen. Also, you are introducing concurrency.

提交回复
热议问题