Bas*_*lew 15 c# sockets c#-5.0 .net-4.5
我不知道如何在异步方法等待传入连接时正确关闭TcpListener.我在SO上找到了这个代码,这里是代码:
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)
{
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
主要:
static void Main(string[] args)
{
var server = new Server();
server.StartListening();
Thread.Sleep(5000);
server.StopListening();
Console.Read();
}
Run Code Online (Sandbox Code Playgroud)
这条线上有一个例外
await AcceptConnections();
Run Code Online (Sandbox Code Playgroud)
当我调用Server.StopListening()时,该对象被删除.
所以我的问题是,如何取消AcceptTcpClientAsync()以正确关闭TcpListener.
由于这里没有合适的工作示例,这里是一个:
假设您同时拥有cancellationTokenand 的范围tcpListener,那么您可以执行以下操作:
using (cancellationToken.Register(() => tcpListener.Stop()))
{
try
{
var tcpClient = await tcpListener.AcceptTcpClientAsync();
// … carry on …
}
catch (InvalidOperationException)
{
// Either tcpListener.Start wasn't called (a bug!)
// or the CancellationToken was cancelled before
// we started accepting (giving an InvalidOperationException),
// or the CancellationToken was cancelled after
// we started accepting (giving an ObjectDisposedException).
//
// In the latter two cases we should surface the cancellation
// exception, or otherwise rethrow the original exception.
cancellationToken.ThrowIfCancellationRequested();
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
虽然基于Stephen Toub的博客文章有一个相当复杂的解决方案,但使用内置.NET API的解决方案更为简单:
var cancellation = new CancellationTokenSource();
await Task.Run(() => listener.AcceptTcpClientAsync(), cancellation.Token);
// somewhere in another thread
cancellation.Cancel();
Run Code Online (Sandbox Code Playgroud)
此解决方案不会终止待处理的接受呼叫.但其他解决方案也没有这样做,这个解决方案至少更短.
更新:一个更完整的示例,显示取消后应发生的情况:
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();
Run Code Online (Sandbox Code Playgroud)
更新2: Task.Run仅在任务开始时检查取消令牌.要加速终止接受循环,您可能希望注册取消操作:
cancellation.Token.Register(() => listener.Stop());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16558 次 |
| 最近记录: |