C#Tasks.Run,本地变量未指定给任务?缺陷

C#Tasks.Run,本地变量未指定给任务?缺陷,c#,C#,有一只奇怪的虫子 以下的输出是: 范围:100000-125000 范围:100000-125000 范围:100000-125000 范围:100000-125000 这是错误的 如果我在循环中添加一个额外的本地var,则输出是正确的 intax=i; var curtask=Task.Run(()=>Work(ax,blocksize,size)); 输出: 范围:75000-100000 范围:0-25000 范围:25000-50000 范围:50000-75000 (不遵守订单没

有一只奇怪的虫子

以下的输出是:

范围:100000-125000
范围:100000-125000
范围:100000-125000
范围:100000-125000
这是错误的
如果我在循环中添加一个额外的本地
var
,则输出是正确的

intax=i;
var curtask=Task.Run(()=>Work(ax,blocksize,size));
输出:

范围:75000-100000
范围:0-25000
范围:25000-50000
范围:50000-75000
(不遵守订单没关系)

因此,
i
var在创建时没有被赋予任务?
我觉得这种情况非常危险。通常情况下,我会相信这些相似之处

私有静态无效工作(int startIndex、int blocksize、int maxSize)
{
int end=开始索引+块大小;
Trace.WriteLine($“范围:{startIndex}-{end}”);
WriteLine($“范围:{startIndex}-{end}”);
}
静态void Main(字符串[]参数)
{
int i=0;
整数大小=100000;
int blocksize=size/4;
int taskcount=0;
var tasks=新列表();
而(iWork(ax,blocksize,size));
var curtask=Task.Run(()=>Work(i,blocksize,size));
taskcount++;
任务。添加(任务);
i=i+块大小;
}
Task.WaitAll(tasks.ToArray());
控制台。写入线(“完成”);
Console.ReadKey();
}

我觉得一切都很好。我被俘了。您只有一个i,由所有任务共享,但您有许多ax,每个ax都有不同的价值


也许您可以阅读有关闭包的内容,例如:

发生这种情况是因为在
任务上。运行
调用创建的任务不会立即运行,而是仅创建(
WaitingToRun
状态证明了这一点)


例如,第一个创建的任务还没有开始,但另一个迭代已经发生,并且
i
会递增,依此类推。

传递给任务的变量会像通过引用一样被访问(c#保持变量值的更新)。因此,如果将变量
i
发送到每个任务,则其值将随着循环的进行而更新。您必须在发送
i
之前创建一个局部变量,以便在当前时刻向每个任务发送
i
的副本。源代码中对您的注释是正确的方法。

在这里,您的所有任务都是在while循环结束后开始的。因此,它们会看到
i

的最后一个值,这是您在变量上关闭lambda的常见错误。这种行为对大多数人来说是意外的,但却是正确的。如果您在此处搜索“C#lambda闭环变量”或类似的问题,您将发现大量类似的问题。此答案中几乎没有任何内容是正确的。非常感谢@Eric的澄清。我更新了答案以便更准确。