title: StackOverflowExceptions in nested async methods on unwinding of the stack
body: <p>We have a lot of nested async methods and see behavior that we do not really understand. Take for example this simple C# console application</p>
  <pre class="lang-cs prettyprint-override"><code>public class Program
  {
      static void Main(string[] args)
      {
          try
          {
              var x = Test(index: 0, max: int.Parse(args[0]), throwException: bool.Parse(args[1])).GetAwaiter().GetResult();
  
              Console.WriteLine(x);
          }
          catch(Exception ex)
          {
              Console.WriteLine(ex);
          }
          
          Console.ReadKey();
      }
      
      static async Task&lt;string&gt; Test(int index, int max, bool throwException)
      {
          await Task.Yield();
      
          if(index &lt; max)
          {
              var nextIndex = index + 1;
              try
              {
                  Console.WriteLine($&quot;b {nextIndex} of {max} (on threadId: {Thread.CurrentThread.ManagedThreadId})&quot;);
                
                  return await Test(nextIndex, max, throwException).ConfigureAwait(false);
              }
              finally
              {
                  Console.WriteLine($&quot;e {nextIndex} of {max} (on threadId: {Thread.CurrentThread.ManagedThreadId})&quot;);
              }
          }
      
          if(throwException)
          {
              throw new Exception(&quot;&quot;);
          }
      
          return &quot;hello&quot;;
      }
  }
  </code></pre>
  <p>When we run this sample with the following arguments:</p>
  <blockquote>
  <p>AsyncStackSample.exe 2000 false</p>
  </blockquote>
  <p>We get a <code>StackOverflowException</code> and this is the last message we see in the console:</p>
  <blockquote>
  <p>e 331 of 2000 (on threadId: 4)</p>
  </blockquote>
  <p>When we change the arguments into</p>
  <blockquote>
  <p>AsyncStackSample.exe 2000 true</p>
  </blockquote>
  <p>We end with this message</p>
  <blockquote>
  <p>e 831 of 2000 (on threadId: 4)</p>
  </blockquote>
  <p>So the <code>StackOverflowException</code> occurs on the unwinding of the stack (not really sure if we should call it that, but the <code>StackOverflowException</code> occurs after the recursive call in our sample, in synchronous code, a <code>StackOverflowException</code> will always occur on the nested method call). In the case that we throw an exception, the <code>StackOverflowException</code> occurs even earlier.</p>
  <p>We know we can solve this by calling <code>Task.Yield()</code> in the finally block, but we have a few questions:</p>
  <ol>
  <li>Why does the Stack grow on the unwinding path (in comparison to a
  method that doesn't cause a thread switch on the await)?</li>
  <li>Why does the <code>StackOverflowException</code> occurs earlier in the Exception case than when we don't throw an exception?</li>
  </ol>