如果 .NET Task.Run 用于 运行ning CPU 绑定任务,那么在后台启动 IO 绑定任务到 运行 的正确方法是什么?
If .NET Task.Run is for running CPU-bound tasks, what's the right way to start IO-bound tasks to run in the background?
我从头编写了一个网络服务器应用程序,所以没有 IIS 或 Windows 窗体。我一直在使用 Task.Run 将网络会话生命周期的控制权移交给后台的 运行。
类似...
while (true)
{
var tcpClient = tcpListener.Accept...
Task.Run(() => ProcessSession(tcpClient));
}
...然后...
public async Task ProcessSession(TcpClient tcpClient)
{
...
await tcpClient.GetStream().ReadAsync(...)
...
}
我希望当我在 ProcessSession 中对网络 I/O 执行异步/等待时,工作线程将被释放,直到 I/O 完成。
我发现我的服务器软件在只有几百个连接时陷入困境,以至于客户端在尝试连接时超时,或者如果它们连接上了,它们的网络吞吐量确实很慢。我希望每台服务器处理数千个连接。
当我查看 ThreadPool.Get(Max/Available)Threads 时,它看起来并没有发生太多事情。 Process.GetCurrentProcess().Threads.Count 仅在几十个中,因此它不像是每个连接一个线程。它只是陷入困境。
利用网络堆栈的内置异步是正确的解决方案,看起来这就是您使用 TcpClient 所做的事情。
鉴于您 "getting bogged down," 调查瓶颈在哪里。没有人可以在不知道问题是什么的情况下解决性能问题。你的记忆 space 是什么样子的?时间都花在哪儿了? perfmon 说您的服务器进程中发生了什么?
如果ProcessSession
确实没有阻塞那么你可以调用它:
while (true)
{
var tcpClient = tcpListener.Accept...
ProcessSession(tcpClient);
}
并丢弃生成的任务。请务必记录所有错误。
将名称更改为 ProcessSessionAsync
。
我从头编写了一个网络服务器应用程序,所以没有 IIS 或 Windows 窗体。我一直在使用 Task.Run 将网络会话生命周期的控制权移交给后台的 运行。
类似...
while (true)
{
var tcpClient = tcpListener.Accept...
Task.Run(() => ProcessSession(tcpClient));
}
...然后...
public async Task ProcessSession(TcpClient tcpClient)
{
...
await tcpClient.GetStream().ReadAsync(...)
...
}
我希望当我在 ProcessSession 中对网络 I/O 执行异步/等待时,工作线程将被释放,直到 I/O 完成。
我发现我的服务器软件在只有几百个连接时陷入困境,以至于客户端在尝试连接时超时,或者如果它们连接上了,它们的网络吞吐量确实很慢。我希望每台服务器处理数千个连接。
当我查看 ThreadPool.Get(Max/Available)Threads 时,它看起来并没有发生太多事情。 Process.GetCurrentProcess().Threads.Count 仅在几十个中,因此它不像是每个连接一个线程。它只是陷入困境。
利用网络堆栈的内置异步是正确的解决方案,看起来这就是您使用 TcpClient 所做的事情。
鉴于您 "getting bogged down," 调查瓶颈在哪里。没有人可以在不知道问题是什么的情况下解决性能问题。你的记忆 space 是什么样子的?时间都花在哪儿了? perfmon 说您的服务器进程中发生了什么?
如果ProcessSession
确实没有阻塞那么你可以调用它:
while (true)
{
var tcpClient = tcpListener.Accept...
ProcessSession(tcpClient);
}
并丢弃生成的任务。请务必记录所有错误。
将名称更改为 ProcessSessionAsync
。