Possible Duplicate:
C# Captured Variable In Loop
I am pretty new to multi-threading programming. When I ran the code below and only the last child got executed. Can some one tell me what happened? Thank you very much.
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() + "]");
}
}
Output
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]
By using the loop variable in your lambda, all of the effectively refer to the same variable, which is the last item of your dictionary at the time they run.
You need to assign the loop variable to another variable local to the loop before passing it to a lambda. Do this:
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));
}
EDIT: It seems this little pitfall is fixed in C#5. That's why it might work for others ;) See comment by labroo
You can prevent that behavior by assigning kvp to a local variable in the for loop and pass the variables fields Key and Value to the DoSomething method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With