1

i wrote the code:

List<Task> tt = new List<Task>();
for (int i = 0; i < 5; i++)
{
    tt.Add(
    new Task((o) =>
    {
        Thread.Sleep(Convert.ToInt32(o)*1000);
        Console.WriteLine("end of {0}!", Convert.ToInt32(o));
    },i));
}

tt.ForEach(t => t.Start());
Task.WaitAll(tt.ToArray());

and it show me in console: end of 1! (interval 1 sec)

end of 2! (interval 1 sec)

end of 3! (interval 1 sec)

end of 4! (interval 1 sec)

end of 5! (interval 1 sec)

but if i get this code:

List<Task> tt = new List<Task>();
for (int i = 0; i < 5; i++)
{
    tt.Add(
    new Task( () =>
    {
        Thread.Sleep(i*1000);
        Console.Write("end! ");
    }));
}

tt.ForEach(t => t.Start());
Task.WaitAll(tt.ToArray());

then i have this answer: (interval 5 seconds and all in one moment): end! end! end! end! end!

Could you explain me this phenomenon?

I think that:

This is due to the fact that the variable "i" is continuously incremented and thread has access to the variables? In this case, each thread will remember the last value "i" so each thread will wait for 5 seconds and just send a message?

It's good reason?

cniak
  • 301
  • 2
  • 6
  • 13
  • Yes, you've got a single `i` variable which is being captured by all the tasks. If you declare a local variable *inside the loop* which takes a copy of `i`, and use that copy in your lambda expression, it will be fine. – Jon Skeet Apr 04 '14 at 09:17

1 Answers1

0

In the second case the last value of i is used which is 5 due to capture closure of loop variable, you can assign the value of loop variable to some local variable and use that in task,

List<Task> tt = new List<Task>();
for (int i = 0; i < 5; i++)
{
    int temp = i;
    tt.Add(
    new Task( () =>
    {
        Thread.Sleep(temp * 1000);
        Console.Write("end! ");
    }));
}

tt.ForEach(t => t.Start());
Task.WaitAll(tt.ToArray());
Community
  • 1
  • 1
Adil
  • 146,340
  • 25
  • 209
  • 204