Have you ever got the following message from ReSharper.

Access to modified closure

I've seen this message many times and have spent some time researching it. It's a very interesting problem that could cause you a good bit of pain. Anyone who has developed software for any amount of time knows that writing code takes much less time than debugging code. If you are not careful this issue could have you debugging for hours.

This weekend I was doing some testing outside Visual Studio in a program called LINQPad. This means ReSharper could not have my back. The test code I was writing needed to open 15 threads and post data to a web API. I used some naming convention (Customer1, Customer2, etc) to access some test data which means I was using my for "i" variable when starting up my threads. Yep, I feel into the issue yet again...

Here is a simple example program to demonstrate the issue.

private static void Main(string[] args)
{
    var tasks = new Task[10];
    for (var i = 0; i < 10; i++)
    {
        tasks[i] = Task.Run(() => PrintNumber(i));
    }

    Task.WaitAll(tasks);
    Console.WriteLine("Press any key to exit.");
    Console.ReadKey();
}

private static void PrintNumber(int i)
{
    Console.WriteLine(i);
}

At first glance you would expect this code to simple the numbers 0-9 in no specific order being that we are multi-threaded. However the sample will only print "10". The problem is on line 6 when we pass "i" to the PrintNumber method. The last value of "i" is what will be used when the RunNumber method is invoked. All the anonymous methods print the same number because they are all sharing the same outer scope "i" variable.

What we need is to ensure the correct value is passed into the method when it is called. We do this by simply assigning the value "i" to another local variable that is only accessible by the inner scope of the loop. This will ensure that the proper value is passed into the method when the method is actually invoked.

private static void Main(string[] args)
{
    var tasks = new Task[10];
    for (var i = 0; i < 10; i++)
    {
        var number = i;
        tasks[i] = Task.Run(() => PrintNumber(number));
    }

    Task.WaitAll(tasks);
    Console.WriteLine("Press any key to exit.");
    Console.ReadKey();
}

private static void PrintNumber(int i)
{
    Console.WriteLine(i);
}

Just be aware of this issue because it is really easy to over look and allow it to really cause havoc inside your application.