title: Recursion and the await / async Keywords
body: <p>I have a fragile grasp of how the <code>await</code> keyword works, and I want to extend my understanding of it a bit.</p>
  
  <p>The issue that still makes my head spin is the use of recursion. Here's an example:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  
  namespace TestingAwaitOverflow
  {
      class Program
      {
          static void Main(string[] args)
          {
              var task = TestAsync(0);
              System.Threading.Thread.Sleep(100000);
          }
  
          static async Task TestAsync(int count)
          {
              Console.WriteLine(count);
              await TestAsync(count + 1);
          }
      }
  }
  </code></pre>
  
  <p>This one obviously throws a <code>StackOverflowException</code>. </p>
  
  <p>My understanding is because the code actually runs synchronously until the first asynchronous action, after which it returns a <code>Task</code> object that contains information about the asynchronous operation. In this case, there is no asynchronous operation, thus it just keeps recursing under the false promise that it will eventually get a <code>Task</code> returned.</p>
  
  <p>Now changing it just a tiny bit:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  
  namespace TestingAwaitOverflow
  {
      class Program
      {
          static void Main(string[] args)
          {
              var task = TestAsync(0);
              System.Threading.Thread.Sleep(100000);
          }
  
          static async Task TestAsync(int count)
          {
              await Task.Run(() =&gt; Console.WriteLine(count));
              await TestAsync(count + 1);
          }
      }
  }
  </code></pre>
  
  <p>This one does not throw a <code>StackOverflowException</code>. I can <em>sortof</em> see why it works, but I would call it more of a gut feeling (it probably deals with how the code is arranged to use callbacks to avoid building the stack, but I can't translate that gut feeling into an explanation)</p>
  
  <p>So I have two questions:</p>
  
  <ul>
  <li>How does the second batch of code avoid a <code>StackOverflowException</code>?</li>
  <li>Does the second batch of code waste other resources? (for example does it allocate an absurdly large number of Task objects on the heap?)</li>
  </ul>
  
  <p>Thanks!</p>