Search code examples
c#monoxamarin.androidwebrequest

Gracefully abort WebRequest on TimeOut/No connection


I am developing an app for Android (and later iphone) using MonoDevelop/C# testing using Android emulator.

I have a WebRequest which I want to get a callback when it times out (or there is no webconnection). At first I got no timeout or callback if the internet connection was down. Here is how I tried to solve it:

private void setupTimeOut (IAsyncResult result, RequestState state)
{
    ThreadPool.RegisterWaitForSingleObject (
        result.AsyncWaitHandle,
        new WaitOrTimerCallback (ScanTimeoutCallback),
        state,
        (5 * 1000),  // 5 second timeout
        true
    );
}

Correctly, ScanTimeoutCallback was called after 5 sec (when I unplugged internet). But ScanTimeout did however throw this exception:

UNHANDLED EXCEPTION: System.Net.WebException: Aborted.
at System.Net.HttpWebRequest.EndGetResponse (System.IAsyncResult) <0x00160>
at MyApp.ServerService.extractResponseAndCallDelegateOnError  
  (System.Net.WebRequest,System.IAsyncResult) <0x0003b>

And the code for ScanTimeoutCallback:

private static void ScanTimeoutCallback (object state, bool timedOut)
{ 
    if (timedOut)
    {
        Console.Out.WriteLine ("timedOut");
        RequestState reqState = (RequestState)state;
        if (reqState != null)
        {
            reqState.Request.Abort ();
            //Call my UI callback
        }
    }
}

The BeginGetResponse:

IAsyncResult result = request.BeginGetResponse (o => {
context.Post (_ => {
    onLogin (o); }, null);
}, state);

setupTimeOut (result, state);

The EndGetResponse:

using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result) as HttpWebResponse)
    { ... }

Solution

  • The exception wasn't thrown by the timeout, but by the EndGetResponse handler.

    You need to handle the exception in your handler:

    try
    {
        using (HttpWebResponse response ...)
        {
           ...
        }
    }
    catch (System.Net.WebException)
    {
        // handle the exception here
    }