Cancel blocking AcceptTcpClient call

后端 未结 5 1488
生来不讨喜
生来不讨喜 2020-12-09 18:00

As everyone may already know, the simplest way to accept incoming TCP connections in C# is by looping over TcpListener.AcceptTcpClient(). Additionally this way will block co

5条回答
  •  一向
    一向 (楼主)
    2020-12-09 18:30

    For completeness, async counterpart of the answer above:

    async Task AcceptAsync(TcpListener listener, CancellationToken ct)
    {
        using (ct.Register(listener.Stop))
        {
            try
            {
                return await listener.AcceptTcpClientAsync();
            }
            catch (SocketException e)
            {
                if (e.SocketErrorCode == SocketError.Interrupted)
                    throw new OperationCanceledException();
                throw;
            }
        }
    }
    

    Update: As @Mitch suggests in comments (and as this discussion confirms), awaiting AcceptTcpClientAsync may throw ObjectDisposedException after Stop (which we are calling anyway), so it makes sense to catch ObjectDisposedException too:

    async Task AcceptAsync(TcpListener listener, CancellationToken ct)
    {
        using (ct.Register(listener.Stop))
        {
            try
            {
                return await listener.AcceptTcpClientAsync();
            }
            catch (SocketException e) when (e.SocketErrorCode == SocketError.Interrupted)
            {
                throw new OperationCanceledException();
            }
            catch (ObjectDisposedException) when (ct.IsCancellationRequested)
            {
                throw new OperationCanceledException();
            }
        }
    }
    

提交回复
热议问题