-1

im starting 10 tasks to get result from web api. Im get IndexOutOfRangeException on offsets array. But how its posible. Actually 'i' variable canot be greater or equal that 10. Can anyone help with this? For loop not working corectly?

            times = 10;
            Task[] tasks = new Task[times];
            int[] offsets = new int[times];

            for (int i = 0; i < times; i++)
            {
                offsets[i] = offset;
                tasks[i] = Task.Run(() => SearchLocalByQuery(query, offsets[i], (i + 1)));
                offset += Limit;
            }
            Task.WaitAll(tasks);

i = 10,

i cannot be 10 in for loop off this example.

System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'

1 Answers1

2

i cannot be 10 in for loop off this example.

It can be in the lambda expression. This expression:

() => SearchLocalByQuery(query, offsets[i], (i + 1))

captures the variable i, and will evaluate that variable value whenever it is executed. Task.Run returns immediately but won't necessarily have started executing the delegate yet - so it's entirely possible that the loop has moved onto the next iteration, or completed, before i is evaluated.

The simple fix for this is to declare a local variable to capture i inside the loop:

for (int i = 0; i < times; i++)
{
    int copy = i;
    offsets[i] = offset;
    // Make sure we only use copy within the lambda expression
    tasks[i] = Task.Run(() => SearchLocalByQuery(query, offsets[copy], copy + 1));
    offset += Limit;
}

Now there'll be a fresh copy variable for each iteration of the loop, and that variable will never change its value - so the lambda expression will execute using "the value of i for that iteration of the loop" regardless of what the current value of i is.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194