本文介绍了TcpListener:如何在等待AcceptTcpClientAsync()时停止监听?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道如何在异步方法等待传入连接时正确关闭TcpListener。
我在SO上找到了此代码,这里的代码是:

I don't know how to properly close a TcpListener while an async method await for incoming connections.I found this code on SO, here the code :

public class Server
{
    private TcpListener _Server;
    private bool _Active;

    public Server()
    {
        _Server = new TcpListener(IPAddress.Any, 5555);
    }

    public async void StartListening()
    {
        _Active = true;
        _Server.Start();
        await AcceptConnections();
    }

    public void StopListening()
    {
        _Active = false;
        _Server.Stop();
    }

    private async Task AcceptConnections()
    {
        while (_Active)
        {
            var client = await _Server.AcceptTcpClientAsync();
            DoStuffWithClient(client);
        }
    }

    private void DoStuffWithClient(TcpClient client)
    {
        // ...
    }

}

和主体:

    static void Main(string[] args)
    {
        var server = new Server();
        server.StartListening();

        Thread.Sleep(5000);

        server.StopListening();
        Console.Read();
    }

此行引发异常

        await AcceptConnections();

当我调用Server.StopListening()时,对象被删除。

when I call Server.StopListening(), the object is deleted.

所以我的问题是,如何取消AcceptTcpClientAsync()以正确关闭TcpListener。

So my question is, how can I cancel AcceptTcpClientAsync() for closing TcpListener properly.

推荐答案

尽管有一个基于复杂的解决方案 / how-do-i-cancel-non-cancelable-async-operations / rel = nofollow noreferrer>博客作者Stephen Toub ,使用内置.NET API的解决方案要简单得多:

While there is a fairly complicated solution based on a blog post by Stephen Toub, there's much simpler solution using builtin .NET APIs:

var cancellation = new CancellationTokenSource();
await Task.Run(() => listener.AcceptTcpClientAsync(), cancellation.Token);

// somewhere in another thread
cancellation.Cancel();

此解决方案不会取消待处理的接受呼叫。但是其他解决方案也没有这样做,并且该解决方案至少更短。

This solution won't kill the pending accept call. But the other solutions don't do that either and this solution is at least shorter.

更新:一个更完整的示例,说明了应该在发出取消信号后发生:

Update: A more complete example that shows what should happen after the cancellation is signaled:

var cancellation = new CancellationTokenSource();
var listener = new TcpListener(IPAddress.Any, 5555);
listener.Start();
try
{
    while (true)
    {
        var client = await Task.Run(
            () => listener.AcceptTcpClientAsync(),
            cancellation.Token);
        // use the client, pass CancellationToken to other blocking methods too
    }
}
finally
{
    listener.Stop();
}

// somewhere in another thread
cancellation.Cancel();

更新2: Task.Run 仅在任务启动时检查取消令牌。为了加快终止接受循环的速度,您可能希望注册取消操作:

Update 2: Task.Run only checks the cancellation token when the task starts. To speed up termination of the accept loop, you might wish to register cancellation action:

cancellation.Token.Register(() => listener.Stop());

这篇关于TcpListener:如何在等待AcceptTcpClientAsync()时停止监听?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-19 00:08