The answers to both questions are related to the closing area when creating an anonymous method.
When you do this:
// Closure for anonymous function call begins here. for (int i = 0; i < 10; ++i) { // i is captured ThreadPool.QueueUserWorkItem(delegate { DoWork("closure", i); }); }
You capture i throughout the cycle. This means that you queue your ten threads very quickly, and by the time they start, closing i will be 10.
To get around this, you reduce the scope by introducing a variable inside the loop, for example:
for (int i = 0; i < 10; ++i) { // Closure extends to here. var copy = i; // **copy** is captured ThreadPool.QueueUserWorkItem(delegate { DoWork("closure", copy); }); }
Here, the closure does not extend beyond the loop, but only to the value inside.
However, the second call to QueueUserWorkItem gives the desired result, because you created Tuple<T1, T2> while the delegate is in the queue, the value is fixed at this point.
Note that in C # 5.0, the behavior for foreach been changed because it happens so often (when the closure closes in a loop) and causes a lot of people headaches (but not for , as you use).
If you want to take advantage of this fact, you can call the Range method on the Enumerable class to use foreach :
foreach (int i in Enumerable.Range(0, 10)) { // Closure for anonymous function call begins here. ThreadPool.QueueUserWorkItem(delegate { DoWork("closure", i); }); }