【发布时间】:2018-11-29 16:33:14
【问题描述】:
我有一段旧代码(.NET 3.5),我在一个单独的线程中运行新 TcpClient 的注册:
旧代码:
public class TcpServer
{
private readonly TcpListener _tcpListener;
public TcpServer(int port)
{
_tcpListener = new TcpListener(IPAddress.Any, port);
}
public void StartListening()
{
_tcpListener.Start();
var t = new Thread(new ThreadStart(AcceptConnections));
t.Start();
}
private void AcceptConnections()
{
while (true)
{
var client = _tcpListener.AcceptTcpClient();
// Some stuff
}
}
}
此代码的目的是避免在等待新客户端时阻塞应用。我正在将此代码移植到 .NET Standard,我想知道是否必须使用 .NET 的新功能。
我说的是async/await和Task。
异步线程版本
由于这个线程将持续整个应用程序,我首先考虑用新的异步方法简单地替换实际方法。但如果我这样做,我最终会得到一个运行async void 方法的新线程:
public class TcpServer
{
private readonly TcpListener _tcpListener;
public TcpServer(int port)
{
_tcpListener = new TcpListener(IPAddress.Any, port);
}
public void StartListening()
{
_tcpListener.Start();
var t = new Thread(new ThreadStart(AcceptConnectionsAsync));
t.Start();
}
private async void AcceptConnectionsAsync()
{
while (true)
{
var client = await _tcpListener.AcceptTcpClientAsync();
// Some stuff
}
}
}
不建议编写async void 方法,除非在极少数情况下(如事件处理程序)。
这种情况可以接受吗?
异步任务版本
作为一个新选项,我在Task 中运行注册:
public class TcpServer
{
private readonly TcpListener _tcpListener;
public TcpServer(int port)
{
_tcpListener = new TcpListener(IPAddress.Any, port);
}
public Task StartListeningAsync()
{
_tcpListener.Start();
return Task.Run(async () => await AcceptConnectionsAsync());
}
private async Task AcceptConnectionsAsync()
{
while (true)
{
var client = await _tcpListener.AcceptTcpClientAsync();
// Some stuff
}
}
}
有了这段代码,只要我不awaitAcceptConnectionsAsync调用,应用程序就不会被阻塞(我用while(true)简化了代码,但我处理了应用程序的关闭和结束正确地听,我可以在那里调用 await ,甚至可以忽略它)。
但正如我所说,这个动作应该和整个应用程序一样长,我认为一个新线程更合适(至少在架构方面,但在效率方面也是如此)。
我错了吗?
不要对这部分代码做任何改动
这是我看到的最后一个选项。我打算用 Async/Await 更新代码,因为我读到 async/await 提高了 TcpListener 的性能。
但这是真的吗?
重要信息
以下是一些我认为可能相关的信息。不要犹豫询问更多细节。
- 运行此代码的应用程序是控制台应用程序。我知道这对于异步/等待上下文可能很重要?
-
AcceptConnections(Async)方法为每个新连接运行一个新任务(这些任务是短暂的,属于即发即弃类型)。 - 主线程执行大量计算。最好的解决方案是对主线程性能的影响最小。
- 还有一个其他线程的行为与此类似(持续时间相同),负责侦听来自所有客户端的数据。我打算应用与此相同的操作。
【问题讨论】:
-
Is this case acceptable?是事件处理程序吗?为什么要使用async void而不是async Task? stackoverflow.com/questions/44364092/… 有帮助吗? -
因为
ThreadStart构造函数只接受返回void的委托。 -
你为什么要使用
ThreadStartvsTask? -
在我的研究中没有找到您的链接......太糟糕了,它回答了我的部分问题。关于你的第二个问题,我读到
Task不适合长期行动。这就是为什么我希望改用Thread。 -
见stackoverflow.com/questions/37607911/…@fharreau
标签: c# multithreading async-await task