在lambda中使用循环变量

Gus*_*dor -3 c# lambda for-loop

这个行为是在c#中定义的吗?

static void Main(string[] args)
{
    for (int i = 0; i < 10; i++)
    {
        Task.Run(() => Console.WriteLine("This is task " + i));
    }

    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

产量

This is task 10
This is task 10
This is task 10
This is task 10
This is task 10
This is task 10
This is task 10
This is task 10
This is task 10
This is task 10
Run Code Online (Sandbox Code Playgroud)

我知道如何解决它,我知道它为什么会发生,但它是一个定义的行为?

Dou*_*las 5

不,它不是定义的行为.这是一种竞争条件,其中每个输出可以是任何顺序的0到10之间的任何值.它取决于相对于主程序执行生成的任务的时间; 反过来,这在很大程度上取决于机器的多处理能力.如果某个任务碰巧被工作线程拾取并循环完成之前执行,那么您将获得在该时间点发生在循环计数器中的任何值.

你经常得到循环计数器的最终值的原因是主循环在计算上是微不足道的,并且在任何任务有机会运行之前完成.如果要观察非确定性,请在循环中添加一个人工延迟:

for (int i = 0; i < 10; i++)
{
    Task.Factory.StartNew(() => Console.WriteLine("This is task " + i));
    Thread.SpinWait(20000);
}
Run Code Online (Sandbox Code Playgroud)

英特尔酷睿i7上的示例输出:

This is task 2
This is task 3
This is task 3
This is task 3
This is task 4
This is task 5
This is task 7
This is task 8
This is task 9
This is task 8
Run Code Online (Sandbox Code Playgroud)

如果使用足够大的延迟,任务将有机会以直观预期的顺序运行,输出0, 1, 2, ..., 9.