Reputation: 185
The problem i am having seems to be related to task creation. After using a loop to populate a task array, and starting them within a separate loop, my results, although consistent, are wrong. However, if i populate the array individually, the start each task within a loop, everything is fine. Can any one offer me some advice?
For example, this is problematic:
int c = 1;
for (int i = 1; i <= 4; i++)
{
taskArray[i-1] = new Task(() => calculateRows(c, true));
c = c + 2;
}
foreach (Task t in taskArray) t.Start();
but this works fine:
taskArray[0] = new Task(() => calculateRows(1, true));
taskArray[1] = new Task(() => calculateRows(3, true));
taskArray[2] = new Task(() => calculateRows(5, true));
taskArray[3] = new Task(() => calculateRows(7, true));
foreach (Task t in taskArray) t.Start();
Upvotes: 0
Views: 96
Reputation: 1500485
The problem is that your lambda expression captures c
- the variable c
, not its value at the time of task creation. So by the time you start the tasks, c
will be 9. Even if you started them within the loop, there's still no guarantee that the code in the lambda expression will start to execute before the change to c
.
To fix this, you can use a separate local variable for each iteration of the loop:
int c = 1;
for (int i = 1; i <= 4; i++)
{
int temp = c;
taskArray[i-1] = new Task(() => calculateRows(temp, true));
c = c + 2;
}
foreach (Task t in taskArray)
{
t.Start();
}
Or bypass c
entirely and compute temp
from i
:
for (int i = 1; i <= 4; i++)
{
int temp = i * 2 - 1;
taskArray[i-1] = new Task(() => calculateRows(temp, true));
}
foreach (Task t in taskArray)
{
t.Start();
}
Do you need these all to be separate tasks though? Could you use Parallel.For
instead? Or perhaps Enumerable.Range
as suggested in comments:
var tasks = Enumerable.Range(1, 4)
.Select(x => new Task(() => calculateRows(x * 2 - 1, true)
.ToArray();
foreach (Task t in tasks)
{
t.Start();
}
Upvotes: 6