I have come across a situation where Tasks I am creating only seem to work when I am debugging the code.
As you will see below I keep getting a index out of range exception which should not be possible as the loop should never get to 5.
If I add a break point to the loop and then keep pressing F10 through to the end of the program all works as expected.
Any ideas what I am doing wrong?
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int[] numbers = new int[5] { 1, 2, 3, 4, 5 };
List<int> nums = new List<int>();
var tasks = new Task[5];
for (int i = 0; i < numbers.Length; i++)
{
tasks[i] = Task.Factory.StartNew(() =>
{
nums.Add(numbers[i]);
},
TaskCreationOptions.None);
}
Task.WaitAll(tasks);
for (int i = 0; i < nums.Count; i++)
{
Console.WriteLine(nums[i]);
}
Console.ReadLine();
}
}
}
I would expect to see 1, 2, 3, 4, 5 but not in any particular order as running async
Strangely this does work but I don’t see the difference other than the extra typing.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int[] numbers = new int[5] { 1, 2, 3, 4, 5 };
List<int> nums = new List<int>();
var tasks = new Task[5]
{
Task.Factory.StartNew(() => {nums.Add(numbers[0]);}, TaskCreationOptions.None),
Task.Factory.StartNew(() => {nums.Add(numbers[1]);}, TaskCreationOptions.None),
Task.Factory.StartNew(() => {nums.Add(numbers[2]);}, TaskCreationOptions.None),
Task.Factory.StartNew(() => {nums.Add(numbers[3]);}, TaskCreationOptions.None),
Task.Factory.StartNew(() => {nums.Add(numbers[4]);}, TaskCreationOptions.None)
};
Task.WaitAll(tasks);
for (int i = 0; i < nums.Count; i++)
{
Console.WriteLine(nums[i]);
}
Console.ReadLine();
}
}
}
Thanks
Mike
Since the task happens outside the loop, which has finished by the time the task executes, i at this time is 5 (loop exit condition).
In your second example, you dont use i, but instead hard code the values so the problem disappears.
In the debugger, the timing is different and the tasks can execute before the loop completes: again, the problem disappears.
I think you could fix it like this: