title: How to track .Net thread pool usage?
body: <p>AFAIK some methods in the .Net library are able to do <strong>I/O jobs asynchronously without consuming a thread from the pool</strong>.</p>
  
  <p>If my information are correct the <strong>WebClient</strong> *Async methods do that.</p>
  
  <p>I'd like to verify it by checking that effectively threads from the pool are not used during a download.</p>
  
  <p>So my general question is : <strong>how can I monitor the current state of the thread-pool?</strong></p>
  
  <ul>
  <li><p>number of threads</p></li>
  <li><p>number of busy threads</p></li>
  </ul>
  
  <p>Is there some <strong>API</strong> (<em>GetAvailableThreads</em>?) or <strong>performance counters</strong> that would give this information?</p>
  
  <hr>
  
  <p>EDIT: here are some more details</p>
  
  <p>I'm writing a simple benchmark for educational purposes:</p>
  
  <pre><code>string[] urls = Enumerable.Repeat("http://google.com", 32).ToArray();
  /*{
      "http://google.com",
      "http://yahoo.com",
      "http://microsoft.com",
      "http://wikipedia.com",
      "http://cnn.com",
      "http://facebook.com",
      "http://youtube.com",
      "http://twitter.com"
  };*/
  
  /*Task.Run(() =&gt;
      {
          while (true)
          {
              int wt, cpt;
              ThreadPool.GetAvailableThreads(out wt, out cpt);
              Console.WriteLine("{0} / {1}", wt, cpt);
              Thread.Sleep(100);
          }
      });*/
  
  WebClient webClient = new WebClient();
  Stopwatch stopwatch = Stopwatch.StartNew();
  foreach (string url in urls)
  {
      webClient.DownloadString(url);
      Console.WriteLine("Got '{0}'", url);
  }
  stopwatch.Stop();
  
  TimeSpan sequentialTime = stopwatch.Elapsed;
  
  stopwatch.Restart();
  CountdownEvent cde = new CountdownEvent(1);
  foreach (string url in urls)
  {
      cde.AddCount();
      webClient = new WebClient();
      webClient.DownloadStringCompleted += (_, __) =&gt;
      {
          Console.WriteLine("Got '{0}'", __.UserState);
          cde.Signal();
      };
      webClient.DownloadStringAsync(new Uri(url), url);
  }
  cde.Signal();
  cde.Wait();
  stopwatch.Stop();
  
  TimeSpan asyncTime = stopwatch.Elapsed;
  
  stopwatch.Restart();
  ThreadLocal&lt;WebClient&gt; threadWebClient = new ThreadLocal&lt;WebClient&gt;(() =&gt; new WebClient());
  urls.AsParallel().WithDegreeOfParallelism(urls.Length).ForAll(url =&gt; threadWebClient.Value.DownloadString(url));
  stopwatch.Stop();
  
  TimeSpan PLinqTime = stopwatch.Elapsed;
  
  Console.WriteLine("Sequential time: {0}.", sequentialTime);
  Console.WriteLine("PLinq time: {0}.", PLinqTime);
  Console.WriteLine("Async time: {0}.", asyncTime);
  </code></pre>
  
  <p>I'm comparing :</p>
  
  <ul>
  <li>naive sequential loop</li>
  <li><strong>PLINQ</strong> loop</li>
  <li><strong>async I/Os</strong></li>
  </ul>
  
  <p>The interesting part are the last two.</p>
  
  <p>I expect and try to prove that async I/Os are:</p>
  
  <ul>
  <li><p><strong>faster</strong> because they will create less pressure on the pool (less threads need to be created...)</p></li>
  <li><p><strong>lighter</strong> because they will consume less thread of the pool</p></li>
  </ul>
  
  <p>My "benchmark" shows that it's faster and I guess that's because the pool does not need to allocate new threads for each request whereas with PLINQ each parallel request will block one thread.</p>
  
  <p>Now I'd like to check the numbers about thread consumption.</p>
  
  <p>The commented task was a poor attempt to monitor the pool. It may be the good starting point but until now the result are not really consistent with what I expect: it never displays that more than 3/4 threads are consumed, whereas I expect something like 32 threads busy.</p>
  
  <p>I'm open to any idea to enhance it or better any other use-case that would clearly highlight the differences between the two approaches.</p>
  
  <p>Hope this is clearer now, and sorry for not having provided the details sooner. :)</p>