2012-03-08 55 views
10

可能重复:
C# Captured Variable In Loop困惑在一个循环中多线程的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() + "]"); 
    } 
} 

输出


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] 
+0

雅,控制台应用程序。 – Dreteh 2012-03-08 07:23:25

回答

12

通过在您的拉姆达使用循环变量,所有的有效指的是同一个变量,这是你的字典中的最后一项在他们跑步的时间。

您需要先将循环变量分配给循环的另一个变量,然后再将其传递给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)); 
} 

编辑:它似乎这个小陷阱是固定在C#5。这就是为什么它可能适用于其他人;)请参见labroo

+2

人应该真的解释为什么他们downvoted,似乎是一个合理的解释给我 – 2012-03-08 07:18:31

+2

为什么downvote,我不知道这是否是解决方案,但它是一个有效的变化....... http://blogs.msdn .com/b/ericlippert/archive/2009/11/12/closing-the-loop-variable-considered-harmful.aspx – labroo 2012-03-08 07:20:07

+0

也想知道。我的答案看不到任何错误。 – Botz3000 2012-03-08 07:20:49

1

您可以通过将kvp分配给for循环中的局部变量并将变量字段Key和Value传递给DoSomething方法来阻止该行为。

+0

谢谢。我也想到了,但我不明白为什么。 – Dreteh 2012-03-08 07:24:45