7

ここでの考え方は単純ですが、実装にはいくつかの興味深いニュアンスがあります。これは、 .NET 4で実装したい拡張メソッドのシグネチャです。

public static Task<WebResponse> GetResponseAsync(this WebRequest request, CancellationToken token);

これが私の最初の実装です。私が読んだことから、タイムアウトのために Web リクエストをキャンセルする必要があるかもしれません。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 と共に使用した場合、実際に期待どおりに動作しますか?

4

1 に答える 1