1
\$\begingroup\$

I want to make a extension that extends HttpWebRequest in order to retrieve the response asynchronously. This is achieved by using the Task.Factory.FromAsync. Now this extension needs to be able to handle cancellations as well as timeouts.

The way I implemented the cancellation is via registering the request.abort() to the cancellation token. The timeout is handled by running the asynchronous operation inside an other task. It waits on that task with the the given timeout as shown below.

I have tested this method and it works, but I want to know if my implementation is valid (safe practice) with the guidelines. I also want to know if there is a better way to achieve what I need. I am pretty sure that I am adding extra overhead because of the task inside a task situation.

internal static Task<WebResponse> GetResponseAsync(this HttpWebRequest request, TimeSpan timeout,
            CancellationToken token)
        {
            return Task.Run(() =>
            {
                if (token.IsCancellationRequested)
                    return null;
                Task<WebResponse> task;

                try
                {
                    token.Register(request.Abort);
                    task = Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null);

                    if (!task.Wait(timeout))
                        throw new WebException("No response was received during the time-out period specified.",
                            WebExceptionStatus.Timeout);
                }
                catch (Exception ex)
                {
                    var exception = ex as WebException;
                    if (exception != null)
                        throw exception;

                    throw new WebException(ex.Message, WebExceptionStatus.ConnectionClosed);
                }

                return task.Result;
            }, token);
        }

Edit: I have modified my extension method; the new code looks better but it still has the issue of overhead because of two tasks. What do you guys think?

internal static async Task<WebResponse> GetResponseAsync(this HttpWebRequest request, int timeout,
        CancellationToken token)
    {
        var requestTask = Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null);
        var timeOutTask = Task.Delay(timeout, token);

        var result = await Task.WhenAny(requestTask, timeOutTask).ConfigureAwait(false);

        if (result != timeOutTask) return requestTask.Result;

        request.Abort();

        if (token.IsCancellationRequested)
            throw new WebException("Request was canceled.", WebExceptionStatus.RequestCanceled);

        throw new WebException("Request timed out.", WebExceptionStatus.Timeout);
    }
\$\endgroup\$
  • 1
    \$\begingroup\$ This question is incomplete. To help reviewers give you better answers, please add sufficient context to your question. The more you tell us about what your code does and what the purpose of doing that is, the easier it will be for reviewers to help you. See also this meta question. \$\endgroup\$ – Phrancis Aug 19 '16 at 16:17
  • \$\begingroup\$ Edited my question in order to better explain my problem / request. As for the reason I am doing this is solely because I need an extension that will be able to execute a webrequest and retrieve the response asynchronously with support for cancellation and time out. \$\endgroup\$ – Gregory Aug 19 '16 at 19:13
  • 1
    \$\begingroup\$ Well, the cancelation doesn't really make sense there as you are not using any loops and the cancellation line will be executed only once. Task Cancellation \$\endgroup\$ – t3chb0t Aug 19 '16 at 19:21
  • \$\begingroup\$ Webrequest is downloading data over the internet... what i need to cancel is this download if the user calls the cancellation token.... \$\endgroup\$ – Gregory Aug 19 '16 at 23:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.