Converting async/await to Task.ContinueWith

I’ve figured out how to do it without async/await or TaskCompletionSource, using nested tasks and Task.Unwrap instead.

First, to address @mikez’s comment, here’s GetResponseAsync implementation for .NET 4.0:

static public Task<WebResponse> GetResponseTapAsync(this WebRequest request)
{
    return Task.Factory.FromAsync(
         (asyncCallback, state) =>
             request.BeginGetResponse(asyncCallback, state),
         (asyncResult) =>
             request.EndGetResponse(asyncResult), null);
}

Now, here’s GetResponseWithRetryAsync implementation:

static Task<HttpWebResponse> GetResponseWithRetryAsync(string url, int retries)
{
    if (retries < 0)
        throw new ArgumentOutOfRangeException();

    var request = WebRequest.Create(url);

    Func<Task<WebResponse>, Task<HttpWebResponse>> proceedToNextStep = null;

    Func<Task<HttpWebResponse>> doStep = () =>
    {
        return request.GetResponseTapAsync().ContinueWith(proceedToNextStep).Unwrap();
    };

    proceedToNextStep = (prevTask) =>
    {
        if (prevTask.IsCanceled)
            throw new TaskCanceledException();

        if (prevTask.IsFaulted && --retries > 0)
            return doStep();

        // throw if failed or return the result
        return Task.FromResult((HttpWebResponse)prevTask.Result);
    };

    return doStep();
}

It’s been an interesting exercise. It works, but I think its the way more difficult to follow, than the async/await version.

Leave a Comment