title: Converting async/await to Task.ContinueWith
body: <p>This question was triggered by comments to <a href="https://stackoverflow.com/a/21326957/1768303">this one</a>:</p>
  
  <p>How to back-port a non-linear <code>async/await</code> code to .NET 4.0 without <code>Microsoft.Bcl.Async</code>?</p>
  
  <p>In the linked question, we have a <code>WebRequest</code> operation we want to retry for a limited number of times, if it keeps failing. The <code>Async/await</code> code could look like this:</p>
  
  <pre><code>async Task&lt;HttpWebResponse&gt; GetResponseWithRetryAsync(string url, int retries)
  {
      if (retries &lt; 0)
          throw new ArgumentOutOfRangeException();
  
      var request = WebRequest.Create(url);
      while (true)
      {
          WebResponse task = null;
          try
          {
              task = request.GetResponseAsync();
              return (HttpWebResponse)await task;
          }
          catch (Exception ex)
          {
              if (task.IsCanceled)
                  throw;
  
              if (--retries == 0)
                  throw; // rethrow last error
  
              // otherwise, log the error and retry
              Debug.Print("Retrying after error: " + ex.Message);
          }
      }
  }
  </code></pre>
  
  <p>From the first thought, I'd use <code>TaskCompletionSource</code>, as something like this (untested):</p>
  
  <pre><code>Task&lt;HttpWebResponse&gt; GetResponseWithRetryAsync(string url, int retries)
  {
      if (retries &lt; 0)
          throw new ArgumentOutOfRangeException();
  
      var request = WebRequest.Create(url);
  
      var tcs = new TaskCompletionSource&lt;HttpWebResponse&gt;();
  
      Action&lt;Task&lt;WebResponse&gt;&gt; proceesToNextStep = null;
  
      Action doStep = () =&gt;
          request.GetResponseAsync().ContinueWith(proceedToNextStep);
  
      proceedToNextStep = (prevTask) =&gt;
      {
          if (prevTask.IsCanceled)
              tcs.SetCanceled();
          else if (!prevTask.IsFaulted)
              tcs.SetResult((HttpWebResponse)prevTask.Result);
          else if (--retries == 0)
              tcs.SetException(prevTask.Exception);
          else
              doStep();
      };
  
      doStep();
  
      return tcs.Task;
  }
  </code></pre>
  
  <p>The question is, <strong>how to do this without <code>TaskCompletionSource</code>?</strong></p>