Cancel NetworkStream.ReadAsync using TcpListener

后端 未结 1 1679
长情又很酷
长情又很酷 2020-12-10 19:24

Consider the following simplified example (ready to roll in LinqPad, elevated account required):

void Main()
{
    Go();
    Thread.Sleep(100000);
}
async vo         


        
相关标签:
1条回答
  • 2020-12-10 19:42

    No, NetworkStream does not support cancellation.

    Unfortunately, the underlying Win32 APIs do not always support per-operation cancellation. Traditionally, you could cancel all I/O for a particular handle, but the method to cancel a single I/O operation is fairly recent. Most of the .NET BCL was written against the XP API (or older), which did not include CancelIoEx.

    Stream compounds this issue by "faking" support for cancellation (and asynchronous I/O, too) even if the implementation doesn't support it. The "fake" support for cancellation just checks the token immediately and then starts a regular asynchronous read that cannot be cancelled. That's what you're seeing happen with NetworkStream.

    With sockets (and most Win32 types), the traditional approach is to close the handle if you want to abort communications. This causes all current operations (both reads and writes) to fail. Technically this is a violation of BCL thread safety as documented, but it does work.

    cts.Token.Register(() => client.Close());
    ...
    catch (ObjectDisposedException)
    

    If, on the other hand, you want to detect a half-open scenario (where your side is reading but the other side has lost its connection), then the best solution is to periodically send data. I describe this more on my blog.

    0 讨论(0)
提交回复
热议问题