title: Chaining tasks of varying return types (TPL and HttpWebRequest)
body: <p>Folks, I'm finding myself in a weird situation. I need to chain tasks of different returning types together. Normally, you can do something like this  </p>
  
  <pre><code>Task&lt;T&gt; t = Task&lt;T&gt;.Factory.StartNew(() =&gt; ... some T instance);
  Task t2 = t.ContinueWith&lt;U&gt;(parent =&gt; ...);
  return Task.WhenAll(t, t2);
  </code></pre>
  
  <p>My complication however, lies in using the <code>FromAsync</code> helper method to wrap a Begin/End pair and convert that into a Task. I'm trying to write an asynchronous client using HttpWebRequest and tasks on .NET 4.0 (so await is not an option).  </p>
  
  <p>My problem is that the return type of <code>FromAsync</code> is a Task itself which prevents me from using it in a <code>ContinueWith</code> method (<code>ContinueWith</code> expects the return type and wraps the data itself in a <code>Task</code> object).</p>
  
  <p>Here is the code I have so far, which yields the correct functional result, but is not truly asynchronous:  </p>
  
  <pre><code>public Task&lt;string&gt; GetHttpRequest(string url, string contentType)
  {
      var httpWebRequest = CreateHttpWebRequest(url, "GET", contentType);
      Task&lt;WebResponse&gt; httpTask = Task.Factory.FromAsync&lt;WebResponse&gt;(httpWebRequest.BeginGetResponse, httpWebRequest.EndGetResponse, null);
  
      return httpTask.ContinueWith(httpAntecedent =&gt;
            {
                WebResponse webResponse = httpAntecedent.Result;
                Stream responseStream = webResponse.GetResponseStream();
                byte[] data = new byte[webResponse.ContentLength];
  
                var streamReadTask = Task&lt;int&gt;.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, data, 0, data.Length, TaskCreationOptions.AttachedToParent);
  
                return streamReadTask.ContinueWith(parent =&gt;
                    {
                        responseStream.Close();
                        webResponse.Close();
  
                        return Encoding.UTF8.GetString(data);
                    });
            }).Result;
  }
  </code></pre>