2013-01-21 28 views
1

伙计们,我发现自己处于一种奇怪的情况。我需要将不同返回类型的任务链接在一起。通常情况下,你可以做这样的事情各种返回类型的链接任务(TPL和HttpWebRequest)

Task<T> t = Task<T>.Factory.StartNew(() => ... some T instance); 
Task t2 = t.ContinueWith<U>(parent => ...); 
return Task.WhenAll(t, t2); 

然而,我的并发症就在于使用FromAsync辅助方法来包装一个开始/结束对和该转换成任务。我试图编写一个异步客户端使用HttpWebRequest和.NET 4.0上的任务(所以等待不是一个选项)。

我的问题是的FromAsync返回类型是任务本身,其防止从我在ContinueWith方法使用它(ContinueWith期望的返回类型并包装在一个Task对象中的数据本身)。

这里是我的代码到目前为止,这将产生正确的功能性的结果,但不是真正的异步:

public Task<string> GetHttpRequest(string url, string contentType) 
{ 
    var httpWebRequest = CreateHttpWebRequest(url, "GET", contentType); 
    Task<WebResponse> httpTask = Task.Factory.FromAsync<WebResponse>(httpWebRequest.BeginGetResponse, httpWebRequest.EndGetResponse, null); 

    return httpTask.ContinueWith(httpAntecedent => 
      { 
       WebResponse webResponse = httpAntecedent.Result; 
       Stream responseStream = webResponse.GetResponseStream(); 
       byte[] data = new byte[webResponse.ContentLength]; 

       var streamReadTask = Task<int>.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, data, 0, data.Length, TaskCreationOptions.AttachedToParent); 

       return streamReadTask.ContinueWith(parent => 
        { 
         responseStream.Close(); 
         webResponse.Close(); 

         return Encoding.UTF8.GetString(data); 
        }); 
      }).Result; 
} 
+0

'return Task.WhenAll(t,t2);'Task.WhenAll没有这样的过载。 –

+0

@HamletHakobyan确实如此,那是因为它是一个'params'方法(至少在.Net 4.5上,在4.0上,根本没有'WhenAll()')。 – svick

+0

如果您使用VS2012和[Microsoft.Bcl.Async](http://nuget.org/packages/Microsoft.Bcl.Async),则可以在.Net 4.0上使用'await'。 – svick

回答

3

重组你的问题,你有Task<Task<string>>,你想从Task<string>,没有同步等待Task完成。

在C#5.0中,您可以使用双重awaitreturn await await task;来完成此操作。如果没有C#5.0,您可以使用Unwrap(),它完全符合您的要求:return task.Unwrap();

如果出于某种原因想要自己做这件事,可以在ContinueWith()内使用ContinueWith()以及TaskCompletionSource


但是你的代码是有缺陷的:它假设你将在一次读取中得到整个响应。这并没有得到保证,事实上也不会经常正确地工作。正确执行此操作需要更复杂的代码,并且可能还需要TaskCompletionSource

+0

谢谢@svick。 Unwrap正是我所期待的。我引入了一个循环来正确读取整个响应,正如你所建议的那样,并且显着地改变了代码的结构(我不再需要解包)! – Ameen