问题描述
我不知道如何在异步方法等待传入连接时正确关闭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()时停止监听?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!