簡體   English   中英

鏈接不同返回類型的任務(TPL和HttpWebRequest)

[英]Chaining tasks of varying return types (TPL and HttpWebRequest)

伙計們,我發現自己陷入了一種奇怪的境地。 我需要將不同返回類型的任務鏈接在一起。 通常,你可以做這樣的事情

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

然而,我的復雜性在於使用FromAsync輔助方法來包裝Begin / End對並將其轉換為Task。 我正在嘗試使用HttpWebRequest和.NET 4.0上的任務編寫異步客戶端(所以await不是一個選項)。

我的問題是FromAsync的返回類型是一個Task本身,它阻止我在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;
}

要重新解釋您的問題,您有Task<Task<string>>並且您希望從中獲取Task<string> ,而無需同步等待Task完成。

在C#5.0中,您可以通過使用double await來執行此操作: return await await task;

沒有C#5.0,你可以使用Unwrap() ,它完全符合你的需要: return task.Unwrap();

如果由於某種原因,你想自己做這件事,你可以在ContinueWith()使用ContinueWith()TaskCompletionSource


但是你的代碼存在缺陷:它假設你將在一次讀取中獲得整個響應。 這根本不能保證,實際上不會經常正常工作。 正確地執行此操作將需要更復雜的代碼,並且可能還需要TaskCompletionSource

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM