Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foreach loop and tasks

I know from the codeing guidlines that I have read you should not do

for (int i = 0; i < 5; i++) 
{ 
    Task.Factory.StartNew(() => Console.WriteLine(i));
}
Console.ReadLine();

as it will write 5 5's, I understand that and I think i understand why it is happening. I know the solution is just to do

for (int i = 0; i < 5; i++) 
{ 
    int localI = i;
    Task.Factory.StartNew(() => Console.WriteLine(localI));
}
Console.ReadLine();

However is something like this ok to do?

foreach (MyClass myClass in myClassList) 
{ 
    Task.Factory.StartNew(() => myClass.DoAction());
}
Console.ReadLine();

Or do I need to do the same thing I did in the for loop.

foreach (MyClass myClass in myClassList) 
{ 
    MyClass localMyClass = myClass;
    Task.Factory.StartNew(() => localMyClass.DoAction());
}
Console.ReadLine();
like image 363
Scott Chamberlain Avatar asked May 27 '10 21:05

Scott Chamberlain


Video Answer


1 Answers

It's absolutely the same problem with foreach. The following:

foreach (MyClass myClass in myClassList) 
{ 
    Task.Factory.StartNew(() => myClass.DoAction());
}

will most probably always invoke the DoAction method on the last element of the list, which could be fixed like this:

foreach (MyClass myClass in myClassList) 
{ 
    MyClass localMyClass = myClass;
    Task.Factory.StartNew(() => localMyClass.DoAction());
}

But instead of relying on local variables I would recommend you the following:

for (int i = 0; i < 5; i++)
{
    Task.Factory.StartNew(localI => Console.WriteLine(localI), i);
}
like image 143
Darin Dimitrov Avatar answered Nov 08 '22 21:11

Darin Dimitrov