This is easier to understand if you look at what happens, in terms of scope:
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(() => new PhoneJobTest(i);
t.Start();
}
Basically translates to something very close to this:
int i = 0;
while (i < 10)
{
Thread t = new Thread(() => new PhoneJobTest(i);
t.Start();
i++;
}
When you use a lambda expression, and it uses a variable declared outside of the lambda (in your case, i
), the compiler creates something called a closure - a temporary class that "wraps" the i variable up and provides it to the delegate generated by the lambda.
The closure is constructed at the same level as the variable (i), so in your case:
int i = 0;
ClosureClass = new ClosureClass(ref i); // Defined here! (of course, not called this)
while (i < 10)
{
Thread t = new Thread(() => new PhoneJobTest(i);
t.Start();
i++;
}
Because of this, each Thread gets the same closure defined.
When you rework your loop to use a temporary, the closure is generated at that level instead:
for (int i = 0; i < 10; i++)
{
int jobNum = i;
ClosureClass = new ClosureClass(ref jobNum); // Defined here!
Thread t = new Thread(() => new PhoneJobTest(jobNum);
t.Start();
}
Now, each Thread gets its own instance, and everything works properly.