根据
If async-await doesn't create any additional threads, then how does it make applications responsive?
由await执行的C#任务...不会为目标任务创建单独的线程。然而,我观察到,这样的任务并不是每次都从同一个线程执行,而是可以切换它的线程。
我还是不明白,到底是怎么回事。
public class TestProgram
{
private static async Task HandleClient(TcpClient clt)
{
using NetworkStream ns = clt.GetStream();
using StreamReader sr = new StreamReader(ns);
while (true)
{
string msg = await sr.ReadLineAsync();
Console.WriteLine($"Received in {System.Threading.Thread.CurrentThread.ManagedThreadId} :({msg.Length} bytes):\n{msg}");
}
}
private static async Task AcceptConnections(int port)
{
TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), port);
listener.Start();
while(true)
{
var client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
Console.WriteLine($"Accepted connection for port {port}");
var task = HandleClient(client);
}
}
public async static Task Main(string[] args)
{
var task1=AcceptConnections(5000);
var task2=AcceptConnections(5001);
await Task.WhenAll(task1, task2).ConfigureAwait(false);
}
}此示例代码为端口5000和5001创建两个侦听器。其中每一个都可以接受多个连接,并独立于创建的套接字进行读取。
也许它不是“很好”,但它是有效的,我观察到,从不同套接字接收的消息有时在同一个线程中处理,用于执行的线程甚至会发生变化。
Accepted connection for port 5000
Accepted connection for port 5000
Accepted connection for port 5001
Received new message in 5 :(17 bytes):
Port-5000 Message from socket-1
Received new message in 7 :(18 bytes):
Port-5000 Message from socket-1
Received new message in 7 :(18 bytes):
Port-5000 Message from socket-1
Received new message in 7 :(20 bytes):
Port-5000 Message from socket-2
Received new message in 7 :(18 bytes):
Port-5000 Message from socket-2
Received new message in 7 :(18 bytes):
Port-5001 Message from socket-3
Received new message in 8 :(17 bytes):
Port-5001 Message from socket-3
(texts manually edit for clarity, byte lengths are not valid)如果负载很重(我还没有测试它),那么需要多少线程才能执行这些并行任务?我听说过线程池,但不知道如何对它产生一些影响。
或者,问这个问题是完全错误的,我根本不必关心使用了什么特定的线程,以及涉及到多少线程?
发布于 2021-01-14 02:42:19
等待一个C#任务,由
执行...不会为目标任务创建单独的线程。
一个重要的更正是:任务不是由await“执行”的。Asynchronous tasks are already in-progress by the time they're returned。消费代码使用await来执行“异步等待”;即,暂停当前方法,并在该任务完成时恢复该方法。
我观察到,这样的任务并不是每次都从同一个线程执行,而是可以切换它的线程。
我观察到,从不同套接字接收的消息有时在同一线程中处理,用于执行的线程甚至会发生变化。
该任务不会在任何地方“执行”。但是async方法中的代码必须运行,并且必须在线程上运行。await captures a "context" when it pauses the method, and when the task completes it uses that context to resume executing the method。控制台应用程序没有上下文,因此该方法在任何可用的线程池线程上恢复。
如果负载很重(我还没有测试它),那么执行这些并行任务需要多少个线程?我听说过线程池,但不知道如何对它产生一些影响。
或者,问这个问题是完全错误的,我根本不必关心使用了什么特定的线程,以及涉及到多少线程?
您通常不需要知道;只要您的代码没有阻塞线程池线程,您通常就没问题。重要的是要注意,在执行I/O时,例如,在侦听/接受新的TCP套接字时,使用的线程为零。There's no thread being blocked there。线程池线程只有在需要时才会被借用。
在大多数情况下,您不必担心它。但如果你需要的话,thread pool有几个可以调整的旋钮。
https://stackoverflow.com/questions/65706556
复制相似问题