对C#循环中的多线程感到困惑

Dre*_*teh 10 c# multithreading

可能重复:
C#捕获的变量循环

我对多线程编程很陌生.当我运行下面的代码,只有最后一个孩子被执行.有人可以告诉我发生了什么吗?非常感谢你.

private void Process()
{
    Dictionary<int, int> dataDict = new Dictionary<int, int>();
    dataDict.Add(1, 2000);
    dataDict.Add(2, 1000);
    dataDict.Add(3, 4000);
    dataDict.Add(4, 3000);

    foreach (KeyValuePair<int, int> kvp in dataDict)
    {
        Console.WriteLine("Ready for [" + kvp.Key.ToString() + "]");
        Task.Factory.StartNew(() => DoSomething(kvp.Value, kvp.Key));
    }

private static void DoSomething(int waitTime, int childID)
{
    {               
        Console.WriteLine("Start task [" + childID.ToString() + "]");
        Thread.Sleep(waitTime);
        Console.WriteLine("End task [" + childID.ToString() + "]");
    }
}
Run Code Online (Sandbox Code Playgroud)

产量


Ready for [1]
Ready for [2]
Ready for [3]
Ready for [4]
Start task [4]
Start task [4]
Start task [4]
Start task [4]
End task [4]
End task [4]
End task [4]
End task [4]
Run Code Online (Sandbox Code Playgroud)

Bot*_*000 12

通过在lambda中使用循环变量,所有有效的引用相同的变量,这是它们运行时字典的最后一项.

在将循环变量传递给lambda之前,需要将循环变量分配给循环本地的另一个变量.做这个:

foreach (KeyValuePair<int, int> kvp in dataDict)
{
    var pair = kvp;
    Console.WriteLine("Ready for [" + pair.Key.ToString() + "]");
    Task.Factory.StartNew(() => DoSomething(pair.Value, pair.Key));
}
Run Code Online (Sandbox Code Playgroud)

编辑:似乎这个小陷阱在C#5中得到修复.这就是为什么它可能适用于其他人;)请参阅labroo的评论

  • 人们应该真正解释为什么他们贬低,对我来说似乎是一个合理的解释 (2认同)
  • 为什么downvote,我不知道这是否是解决方案,但它是一个有效的变化....... http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-过度的循环变量考虑的-harmful.aspx (2认同)