RexCardan
RexCardan

Reputation: 438

Task.WaitAll Index Out Of Bounds Exception Cause

Why does this not every complete? Instead it throws an exception, like the exception wasn't caught. Moreover, the exceptions "Index out of bounds of array" doesn't make sense to me.

        int n = 3;
        string[] names = new string[] { "sally", "fred", "gina" };
        Task[] myTasks = new Task[n];
        for (int y = 0; y < n; y++)
        {
            myTasks[y] = Task.Factory.StartNew(() =>
            {
                Action<string> action = (name) =>
                {
                    try
                    {
                        throw new Exception(name + ", I bet you can't catch me.");
                    }
                    catch (Exception e)
                    {
                        //I caught you... didn't I?
                    }
                };
                action(names[y]);
            });
        }

        Task.WaitAll(myTasks);
        Console.WriteLine("All tasks complete.");//This line is never reached;

Upvotes: 2

Views: 2224

Answers (2)

Colin Smith
Colin Smith

Reputation: 12540

The lambda function you have inside the StartNew parentheses is forming a closure which is "capturing" the outer variable "y"...it doesn't access the value that it was...during the loop iteration...rather, when the captured variable is accessed in that lambda function...that's when it tries to get the value.

Your "y" variable eventually gets to the value "3" (via the loop y++)....because that causes the "loop for the creation of your "Actions")....to exit (i.e. 3 is not less than 3).

But when any of the Tasks that you created is executing the line action(names[y]) it is accessing the closed variable "y"...which "may" have already reached "3"...and the "3" is not a valid index in your array....it all depends on how quickly or slowly those tasks were scheduled as to whether you hit the problem or not...a classic race condition.

Upvotes: 8

RexCardan
RexCardan

Reputation: 438

I did figure out that by setting a variable outside of the task for name

var name = names[y];

and using this instead of accessing the array from within the task, it works. I still don't understand why.

Upvotes: 1

Related Questions