在For迭代中,我将一个Task放入其中。每项任务都有自己的工作。代码如下:
List<Task> lst_tsk = new List<Task>();
List<int> lst_item = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
foreach (var item in lst_item)
{
Task tsk = new Task(() =>
{
Console.WriteLine(item);
});
lst_tsk.Add(tsk);
tsk.Start();
}
foreach (var t in lst_tsk)
{
if (t.IsCompleted == false)
t.Wait();
}
我希望它打印出1,2,3,4,5,6,7,8,9,10。 但它有效并打破了我的想法。 结果是10,10,10,10,10,10,10,10,10,10。
那么如何编辑代码以使事情正确?
答案 0 :(得分:7)
这是关闭和捕获变量的问题,问题在article by Eric Lippert
中完整解释要解决您的问题,请在每次迭代中将项目值复制到一个新变量中:
List<Task> lst_tsk = new List<Task>();
List<int> lst_item = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
foreach (var item in lst_item)
{
var value = item;
Task tsk = new Task(() =>
{
Console.WriteLine(value);
});
lst_tsk.Add(tsk);
tsk.Start();
}
foreach (var t in lst_tsk)
{
if (t.IsCompleted == false)
t.Wait();
}
备注:此问题已通过C#5.0修复:
在C#5中,a的循环变量 foreach将在逻辑上位于循环内,因此闭包将会 每次关闭变量的新副本