Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The answers to both of your question are related to the scope of the closure when you create the anonymous method.</p> <p>When you do this:</p> <pre><code>// Closure for anonymous function call begins here. for (int i = 0; i &lt; 10; ++i) { // i is captured ThreadPool.QueueUserWorkItem(delegate { DoWork("closure", i); }); } </code></pre> <p>You're capturing <code>i</code> across the <em>entire loop</em>. That means that you queue up your ten threads <em>very</em> quickly, and by the time they start, the closure has captured <code>i</code> to be 10.</p> <p>To get around this, you reduce the scope of the closure, by introducing a variable <em>inside the loop</em>, like so:</p> <pre><code>for (int i = 0; i &lt; 10; ++i) { // Closure extends to here. var copy = i; // **copy** is captured ThreadPool.QueueUserWorkItem(delegate { DoWork("closure", copy); }); } </code></pre> <p>Here, the closure doesn't extend beyond the loop, but just to the value inside.</p> <p>That said, the second call to the <a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx" rel="nofollow"><code>QueueUserWorkItem</code></a> produces the desired result because you've created the <a href="http://msdn.microsoft.com/en-us/library/dd268536.aspx" rel="nofollow"><code>Tuple&lt;T1, T2&gt;</code></a> at the time that the delegate is being queued up, the value is fixed at that point.</p> <p>Note that <a href="http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx" rel="nofollow">in C# 5.0, the behavior for <code>foreach</code> was changed because it happens so often (where the closure closes over the loop) and causes a number of people a lot of headaches</a> (but not <code>for</code> like you are using).</p> <p>If you want to take advantage of that fact, you can call the <a href="http://msdn.microsoft.com/en-us/library/system.linq.enumerable.range.aspx" rel="nofollow"><code>Range</code> method</a> on the <a href="http://msdn.microsoft.com/en-us/library/system.linq.enumerable.aspx" rel="nofollow"><code>Enumerable</code> class</a> to use <code>foreach</code>:</p> <pre><code>foreach (int i in Enumerable.Range(0, 10)) { // Closure for anonymous function call begins here. ThreadPool.QueueUserWorkItem(delegate { DoWork("closure", i); }); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload