非常简单的场景。我正在运行一个紧凑的循环,每次迭代都会生成任务。 (不要问为什么。)
static void Main(string[] args)
{
for (int i = 0; i < 1000 * 1000; i++)
Task.Run(() => WriteHelloAsync(i));
Console.ReadLine();
}
static Task WriteHelloAsync(int x)
{
Console.WriteLine($"Hello {x}!");
return Task.CompletedTask;
}
我可以在控制台中看到它以递增方式写入迭代编号。然而,当它达到目标100万时,它就会继续前进。
但为什么?
答案 0 :(得分:2)
这是classic loop-variable closure problem in C#。
你的循环确实停止了一百万。
在百万停止后,你会拨打大量的WriteHelloAsync(i)
电话。
您将i
传递给所有人。您传递给Task.Run()
的lambda不会创建i
的新副本,该副本保留i
时的值{/ 1>特别致电Task.Run()
。它们都具有相同的i
,其值不断变化,直到循环结束。
在我的机器上,我看到的第一个数字是六位数,这意味着i
的值是第一次任务实际到达调用WriteHelloAsync()
时的值。此后不久,它开始做你看到的数百万美元的事情。
试试这个:
static void Main(string[] args)
{
for (int i = 0; i < 1000 * 1000; i++)
{
// The scope of j is limited to the loop block.
// For each new iteration, there is a new j.
var j = i;
Task.Run(() => WriteHelloAsync(j));
}
Console.ReadLine();
}
@Gigi指出,这也适用于foreach
而不是for
:
foreach (var i in Enumerable.Range(0, 1000 * 1000))
{
Task.Run(() => WriteHelloAsync(i));
}