Best approach to Timeout using HttpWebRequest.BeginGetResponse

Felipe Pessoto picture Felipe Pessoto · May 8, 2012 · Viewed 8.1k times · Source

HttpWebRequest.BeginGetResponse doesn´t respect any Timeout properties from HttpWebRequest(Timeout or ReadWriteTimeout).

I read some approaches to get the same results, but I don't know if it's the best way to do it and if I should use for few calls or I can scale it inside loops(I am doing a webcrawler).

The important thing is, initially my code isn´t async, I just need async because my method should accept a CancellationToken.

My concern is about WaitHandles and ThreadPool.RegisterWaitForSingleObject. It isn´t a daily code then I don´t know if I can have problems in the near future.

private static void HandleCancellation(HttpWebRequest request, IAsyncResult getResponseResult, CancellationToken cancellationToken)
{
    using (WaitHandle requestHandle = getResponseResult.AsyncWaitHandle)
    {
        ThreadPool.RegisterWaitForSingleObject(requestHandle, TimeoutCallback, request, request.Timeout, true);

        //If request finish or cancellation is called
        WaitHandle.WaitAny(new[] {requestHandle, cancellationToken.WaitHandle});
    }

    //If cancellation was called
    if (cancellationToken.IsCancellationRequested)
    {
        request.Abort();
        cancellationToken.ThrowIfCancellationRequested();
    }
}

Calling(again, it isn´t async)

IAsyncResult getResponseResult = request.BeginGetResponse(null, null);

HandleCancellation(request, getResponseResult, cancellationToken);

return (HttpWebResponse)request.EndGetResponse(getResponseResult);

Reference: Better approach in management of multiple WebRequest

Answer

Jim Mischel picture Jim Mischel · May 10, 2012

The MSDN documentation for BeginGetResponse has a very good example of how to handle timeouts. It worked quite well for me in my Web crawler.