For Loop result in Overflow with Task.Run or Task.Start
In 2021, You should really just use the built in Parallel.For
for this. It's quite simple to achieve your desired effect:
ConcurrentBag<byte[]> results = new ConcurrentBag<byte[]>();
ParallelLoopResult result = Parallel.For(0, 4, (i, state) => {
results.Add(GetData(i, plcPool[i]));
});
It's probably caused by a closure problem.
Try this:
for (int i = 0; i < 4; i++)
{
//start task with current connection
int index = i;
tasks[index] = Task<byte[]>.Run(() => GetData(index, plcPool[index]));
}
What is probably happening is that when the last thread starts running, the loop has already incremented i
to 4, and that's the value that gets passed to GetData()
. Capturing the value of i
into a separate variable index
and using that instead should solve that issue.
As an example, if you try this code:
public static void Main()
{
Console.WriteLine("Starting.");
for (int i = 0; i < 4; ++i)
Task.Run(() => Console.WriteLine(i));
Console.WriteLine("Finished. Press <ENTER> to exit.");
Console.ReadLine();
}
it will often give you this kind of output:
Starting.
Finished. Press <ENTER> to exit.
4
4
4
4
Change that code to:
public static void Main()
{
Console.WriteLine("Starting.");
for (int i = 0; i < 4; ++i)
{
int j = i;
Task.Run(() => Console.WriteLine(j));
}
Console.WriteLine("Finished. Press <ENTER> to exit.");
Console.ReadLine();
}
and you get something like
Starting.
Finished. Press <ENTER> to exit.
0
1
3
2
Note how it is STILL NOT NECESSARILY IN ORDER! You will see all the correct values printed out, but in an indeterminate order. Multithreading is tricksy!