C# 为什么这个任务生成循环从未停止过?

C# 为什么这个任务生成循环从未停止过?,c#,task,C#,Task,非常简单的场景。我运行一个紧密的循环,在每次迭代中生成任务。(不要问为什么。) static void Main(字符串[]args) { 对于(int i=0;iWriteHelloAsync(i)); Console.ReadLine(); } 静态任务WriteHelloAsync(intx) { Console.WriteLine($“Hello{x}!”); 返回Task.CompletedTask; } 我可以在控制台中看到它以增量方式写入迭代编号。然而,当它达到100万的目标时,

非常简单的场景。我运行一个紧密的循环,在每次迭代中生成任务。(不要问为什么。)

static void Main(字符串[]args)
{
对于(int i=0;i<1000*1000;i++)
Task.Run(()=>WriteHelloAsync(i));
Console.ReadLine();
}
静态任务WriteHelloAsync(intx)
{
Console.WriteLine($“Hello{x}!”);
返回Task.CompletedTask;
}
我可以在控制台中看到它以增量方式写入迭代编号。然而,当它达到100万的目标时,它只是继续前进

但是为什么呢?

这就是问题所在

你的循环停止在一百万

当它停在一百万之后,您会对
WriteHelloAsync(i)
进行大量调用

您正在将
i
传递给所有人。传递给
Task.Run()
的lambda没有创建一个新的
i
副本,该副本保存了
i
在调用
Task.Run()时的值。它们都有相同的
i
,其值在循环结束之前一直在变化

在我这里的机器上,我看到的第一个数字是六位数,这意味着这是任务第一次真正调用
WriteHelloAsync()
时的
I
值。很快,它就开始做你所看到的事情

试试这个:

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();
}
这是最新的

你的循环停止在一百万

当它停在一百万之后,您会对
WriteHelloAsync(i)
进行大量调用

您正在将
i
传递给所有人。传递给
Task.Run()
的lambda没有创建一个新的
i
副本,该副本保存了
i
在调用
Task.Run()时的值。它们都有相同的
i
,其值在循环结束之前一直在变化

在我这里的机器上,我看到的第一个数字是六位数,这意味着这是任务第一次真正调用
WriteHelloAsync()
时的
I
值。很快,它就开始做你所看到的事情

试试这个:

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();
}

闭包很神奇。你能提到决定变量为什么被重用的机制吗?它是一个闭包。我不明白。就在那里。它是
i
。有一个
i
。我以为我已经掌握了闭包。总是感激能学到新东西@EdPlunkett我看到答案的评论中解释了这一点。它在VS2012中已修复,但仅在使用
foreach
时才修复<代码>for
循环仍将显示此行为。@gigidang!现在我正在学习新的东西!闭包很神奇。你能提到决定变量为什么被重用的机制吗?它是一个闭包。我不明白。就在那里。它是
i
。有一个
i
。我以为我已经掌握了闭包。总是感激能学到新东西@EdPlunkett我看到答案的评论中解释了这一点。它在VS2012中已修复,但仅在使用
foreach
时才修复<代码>for
循环仍将显示此行为。@gigidang!现在我正在学习新的东西!这是另一个副本:这是另一个副本:
foreach (var i in Enumerable.Range(0, 1000 * 1000))
{
    Task.Run(() => WriteHelloAsync(i));
}