提问人:Armaho 提问时间:8/29/2023 最后编辑:Theodor ZouliasArmaho 更新时间:8/29/2023 访问量:80
异步运行的任务,即使 Main 方法未声明为异步
Tasks running asynchronously even though Main method is not declared as async
问:
我写了下面的代码,忘记将 Main 方法声明为异步,所以我的猜测是 and 任务应该同步运行。producer
consumer
using System.Collections.Concurrent;
namespace MainProgram;
public class Program
{
public static void Main(string[] args)
{
using var intCollection = new BlockingCollection<int>();
int sum = 0;
Task.Run(() =>
{
Console.WriteLine("Running Producer");
Thread.Sleep(1000);
for (int i = 0; i < 10; i++)
{
intCollection.Add(i);
Console.WriteLine(i);
}
intCollection.CompleteAdding();
});
Task.Run(() =>
{
Console.WriteLine("Running Consumer");
Thread.Sleep(1000);
while (!intCollection.IsCompleted)
{
sum += intCollection.Take();
Console.WriteLine("Thingi Thingi");
}
});
Console.WriteLine("aaabbb");
Console.ReadLine();
}
}
但此代码的输出如下所示:
aaabbb
Running Producer
Running Consumer
0
Thingi Thingi
1
Thingi Thingi
2
Thingi Thingi
3
Thingi Thingi
4
Thingi Thingi
5
Thingi Thingi
6
Thingi Thingi
7
8
9
Thingi Thingi
Thingi Thingi
Thingi Thingi
这让我感到惊讶,因为这些任务似乎是异步运行的。有人可以向我解释一下吗?
答:
0赞
Theodor Zoulias
8/29/2023
#1
Task.Run
方法调用 ThreadPool
上的委托。因此,在调用两次此方法后,生成了 2 个线程来处理工作请求。此时,您的程序至少有 3 个线程处于活动状态:进程的主线程和 .看到两个后台线程同时运行是预期行为。方法是否是无关紧要的。action
ThreadPool
ThreadPool
Main
async
如果您调用了 100 次,则不会立即生成 100 个线程来满足需求。您可以在此处或此处找到创建和销毁线程的算法的描述。它不是很复杂。它涉及一个阈值,该阈值等于计算机中的 CPU 内核数,并且可通过 SetMinThreads
API 进行调整。Task.Run
ThreadPool
ThreadPool
评论
Task.Run
await
async
async
不会使事情异步运行(它纯粹是语法)。它只允许您使用 .await
GetConsumingEnumerable
方法。这不是唯一正确的方法,但却是最简单的方法。while (!intCollection.IsCompleted)
BlockingCollection<T>