7
這裏的想法支持很簡單,但實現有一些有趣的細微差別。這是擴展方法,我想在.NET 4實現的簽名。實現擴展方法WebRequest.GetResponseAsync與的CancellationToken
public static Task<WebResponse> GetResponseAsync(this WebRequest request, CancellationToken token);
這是我最初的實現。從我讀過的網頁請求可能需要cancelled due to a timeout。除此之外頁描述的支持,我想正確地調用request.Abort()
如果取消通過CancellationToken
要求。
public static Task<WebResponse> GetResponseAsync(this WebRequest request, CancellationToken token)
{
if (request == null)
throw new ArgumentNullException("request");
return Task.Factory.FromAsync<WebRequest, CancellationToken, WebResponse>(BeginGetResponse, request.EndGetResponse, request, token, null);
}
private static IAsyncResult BeginGetResponse(WebRequest request, CancellationToken token, AsyncCallback callback, object state)
{
IAsyncResult asyncResult = request.BeginGetResponse(callback, state);
if (!asyncResult.IsCompleted)
{
if (request.Timeout != Timeout.Infinite)
ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, WebRequestTimeoutCallback, request, request.Timeout, true);
if (token != CancellationToken.None)
ThreadPool.RegisterWaitForSingleObject(token.WaitHandle, WebRequestCancelledCallback, Tuple.Create(request, token), Timeout.Infinite, true);
}
return asyncResult;
}
private static void WebRequestTimeoutCallback(object state, bool timedOut)
{
if (timedOut)
{
WebRequest request = state as WebRequest;
if (request != null)
request.Abort();
}
}
private static void WebRequestCancelledCallback(object state, bool timedOut)
{
Tuple<WebRequest, CancellationToken> data = state as Tuple<WebRequest, CancellationToken>;
if (data != null && data.Item2.IsCancellationRequested)
{
data.Item1.Abort();
}
}
我的問題很簡單但具有挑戰性。在與TPL一起使用時,此實現是否會按預期行事?
@ 280Z28謝謝 - 我寫這個沒有VS,所以無法實際測試這一切;) –
@ 280Z28呀 - 正如我couldn'te測試了一下,我並沒有意識到,'Abort'仍然會觸發回調(有道理)。這隻會導致行爲有點偏離,但仍然有效。 (你會得到一個WebException而不是正確的取消)。 –
我編輯您的文章:1)正確描述了我原來的問題(包括1個新的)的2個主要錯誤,2)包含最新的工作代碼,和3)包含顯示下一個成功案例和3個不同的正確行爲測試類失敗案例(取消,超時和404錯誤)。 –