10

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

2 Answers 2

12

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

Sign up to request clarification or add additional context in comments.

9 Comments

people should really explain why they downvoted, seems like a reasonable explanation to me
Why the downvote, I dont know if this is the solution, but it is a valid change....... blogs.msdn.com/b/ericlippert/archive/2009/11/12/…
Was wondering, too. Can't see anything wrong with my answer.
btw, what Botz3000's answer is implying is that all of the threads run...however, by the time they get the chance to run, kvp == 4
I figured that too, but I just don't understand why.
|
1

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.

1 Comment

Thanks. I figured that too, but I just don't understand why.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.