[英]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.