for(int i = 0; i < list.Count(); i++)
{
Task task = new Task(() => DoWork(list[i]));
task.Start();
}
Can someone tell me how I can ensure that the DoWork
function will act on the list at the position i
?
I am having an issue where the task will start at some point after the next iteration of the for
loop so I get duplicate threads essentially.
Yes, the variable is captured by the lambda expression, and you're then modifying it. There are a few simple options:
First, copying the variable to a variable which is instantiated within the loop:
for (int i = 0; i < list.Count; i++)
{
int copy = i;
Task task = new Task(() => DoWork(list[copy]));
task.Start();
}
Now each iteration will capture a different copy
variable, which isn't modified elsewhere.
Second, introducing a local variable but with list[i]
instead:
for (int i = 0; i < list.Count; i++)
{
var item = list[i];
Task task = new Task(() => DoWork(item));
task.Start();
}
Third, and only if you're using C# 5 or later, using foreach
:
foreach (var item in list)
{
Task task = new Task(() => DoWork(item));
task.Start();
}
In earlier versions of C# that would have the same problem as your original code, as a single item
variable would change in each iteration. From C# 5 onwards, each iteration of the foreach
loop introduces a new iteration variable.
As a side note, from .NET 4.5 onwards it's typically simpler to use Task.Run
instead of creating a new task and then starting it.
See more on this question at Stackoverflow