title: SemaphoreSlim.WaitAsync continuation code
body: <p>My understanding of the <code>await</code> keyword was that the code following the <code>await</code> qualified statement is running as the continuation of that statement once it is complete.</p>
  
  <p>Hence the following two versions should produce the same output:</p>
  
  <pre><code>    public static Task Run(SemaphoreSlim sem)
      {
          TraceThreadCount();
          return sem.WaitAsync().ContinueWith(t =&gt;
          {
              TraceThreadCount();
              sem.Release();
          });
      }
  
      public static async Task RunAsync(SemaphoreSlim sem)
      {
          TraceThreadCount();
          await sem.WaitAsync();
          TraceThreadCount();
          sem.Release();
      }
  </code></pre>
  
  <p>But they do not!</p>
  
  <p>Here is the complete program:</p>
  
  <pre><code>using System;
  using System.Threading;
  using System.Threading.Tasks;
  
  namespace CDE
  {
      class Program
      {
          static void Main(string[] args)
          {
              try
              {
                  var sem = new SemaphoreSlim(10);
                  var task = Run(sem);
  
                  Trace("About to wait for Run.");
  
                  task.Wait();
  
                  Trace("--------------------------------------------------");
                  task = RunAsync(sem);
  
                  Trace("About to wait for RunAsync.");
  
                  task.Wait();
              }
              catch (Exception exc)
              {
                  Console.WriteLine(exc.Message);
              }
              Trace("Press any key ...");
              Console.ReadKey();
          }
  
          public static Task Run(SemaphoreSlim sem)
          {
              TraceThreadCount();
              return sem.WaitAsync().ContinueWith(t =&gt;
              {
                  TraceThreadCount();
                  sem.Release();
              });
          }
  
          public static async Task RunAsync(SemaphoreSlim sem)
          {
              TraceThreadCount();
              await sem.WaitAsync();
              TraceThreadCount();
              sem.Release();
          }
  
          private static void Trace(string fmt, params object[] args)
          {
              var str = string.Format(fmt, args);
              Console.WriteLine("[{0}] {1}", Thread.CurrentThread.ManagedThreadId, str);
          }
          private static void TraceThreadCount()
          {
              int workerThreads;
              int completionPortThreads;
              ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
              Trace("Available thread count: worker = {0}, completion port = {1}", workerThreads, completionPortThreads);
          }
      }
  }
  </code></pre>
  
  <p>Here is the output:</p>
  
  <pre><code>[9] Available thread count: worker = 1023, completion port = 1000
  [9] About to wait for Run.
  [6] Available thread count: worker = 1021, completion port = 1000
  [9] --------------------------------------------------
  [9] Available thread count: worker = 1023, completion port = 1000
  [9] Available thread count: worker = 1023, completion port = 1000
  [9] About to wait for RunAsync.
  [9] Press any key ...
  </code></pre>
  
  <p>What am I missing?</p>