0

This issue is really bizarre and has eluded my attempts at debugging. It only occurs when running the app on a Surface tablet. It does not occur on an Asus tablet or while running in Visual Studio. In a particular scenario where Airplane mode has been turned on, a WebException is thrown that I am absolutely unable to catch. I'm not even entirely certain what in my code is causing it to happen, because some of my logging is not happening after a certain point in the code for an unknown reason. I can only assume it's caused by an HttpWebRequest, because of the type of exception being thrown, which appears to be coming from an internal .NET component. Here is the only debugging information I'm able to obtain. It's from the Windows Event Viewer:

Application: <myappname.exe>
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Net.WebException
Stack:
    at System.Net.ServicePoint.ConnectSocketCallback(System.IAsyncResult)
    at System.Net.LazyAsyncResult.Complete(IntPtr)
    at System.Net.ContextAwareResult.Complete(IntPtr)
    at System.Net.LazyAsyncResult.ProtectedInvokeCallback(System.Object, IntPtr)
    at System.Net.Sockets.Socket.ConnectCallback()
    at System.Net.Sockets.Socket.RegisteredWaitCallback(System.Object, Boolean)
    at System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(System.Object, Boolean)

I really wish I had more debugging information to provide, but I've tried everything I can think of with tons of try/catch blocks everywhere and logging after most calls--some of which isn't be executed. Does anyone have any clue as to what could be causing this?

EDIT 1:

Based on traces the exception appears to be thrown somewhere in here. Virtually everything is wrapped in a try/catch block, so I can't see how the WebException could possibly be slipping through.

byte[] bytes = Encoding.UTF8.GetBytes(requestXml.ToString());
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "POST";
request.ContentType = "text/xml";

try
{
    IAsyncResult requestResult = (IAsyncResult)request.BeginGetRequestStream((rAsyncResult) =>
    {
        using (Stream uploadStream = request.EndGetRequestStream(rAsyncResult))
        {
            try
            {
                uploadStream.Write(bytes, 0, bytes.Length);
                uploadStream.Flush();
            }
            catch (Exception e)
            {
                // Exception handling
            }
            finally
            {
                uploadStream.Dispose();
            }
        }

        IAsyncResult responseResult = (IAsyncResult)request.BeginGetResponse((resAsyncResult) =>
        {
            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(resAsyncResult))
                {
                    try
                    {
                        data = ProcessResponse(XmlReader.Create(response.GetResponseStream()));
                    }
                    catch (Exception e)
                    {
                        // Exception handling
                    }
                    finally
                    {
                        response.Dispose();
                    }
                }
            }
            catch (WebException e)
            {
                // Exception handling
            }

        }, null);
    }, null);
}
catch (Exception e)
{
    // Exception handling
}

EDIT 2:

I still have not found an acceptable solution. I'm currently checking the connection type before-hand and not allowing the code to continue if it's not connected to WiFi, Mobile, or Ethernet, but that doesn't catch the condition where it's connected to a network that has no Internet connection. WinRT has no solution to check Internet connectivity, and even the method I'm using is unfriendly to work with (it just passes back a number--http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/d8e76732-19d3-47b3-840f-70d87c75ce9f).

jokeefe
  • 1,836
  • 4
  • 22
  • 27
  • 1
    perhaps showing your code would help.., if there is an exception there is a way to catch it.. perhaps you are trying to catch it incorrectly.. – MethodMan Apr 05 '13 at 16:33
  • @DJ KRAZE The code where I believe the exception is being thrown is posted. – jokeefe Apr 08 '13 at 15:27
  • is that really how your `Exception Code Block` Looks..? you are not handling any exceptions – MethodMan Apr 08 '13 at 15:45
  • @DJ KRAZE No, I trimmed the code before posting to eliminate irrelevant error message logging and business logic. – jokeefe Apr 08 '13 at 15:51

3 Answers3

0

Did you try handling the Application.UnhandledException?

Add the event handler to the event in the App class constructor:

public App()
{
    // keep the rest of the constructor
    this.UnhandledException += OnUnhandledException;
}

In the event handler you can log the exception and mark is handled to prevent the app from closing / crashing:

void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    // log e.Exception details for investigation
    e.Handled = true;
}
Damir Arh
  • 17,637
  • 2
  • 45
  • 83
  • That was the first thing I tried, but thank you for the suggestion. On the WinRT platform that apparently only works for exceptions thrown on the main thread, and this is happening in a different thread. It's a "known limitation:" http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/bea154b0-08b0-4fdc-be31-058d9f5d1c4e. It renders that functionality relatively useless in my opinion. Thanks, though. – jokeefe Apr 05 '13 at 20:53
0

The issue is probably due to an unhandled exception thrown in your callback; chances are high that the callback is executed asynchronously in a thread different from the one that called the initial request.BeginGetRequestStream and this is why you aren't catching it in the outer try/catch block. You should be able to overcome this problem by wrapping the entire content of the callback in a try/catch block, that is:

IAsyncResult requestResult = (IAsyncResult)request.BeginGetRequestStream((rAsyncResult) =>
{
    try
    {
        using (Stream uploadStream = request.EndGetRequestStream(rAsyncResult))
        {
            try
            {
                uploadStream.Write(bytes, 0, bytes.Length);
                uploadStream.Flush();
            }
            catch (Exception e)
            {
                // Exception handling
            }
            finally
            {
                uploadStream.Dispose();
            }
        }

        IAsyncResult responseResult = (IAsyncResult)request.BeginGetResponse((resAsyncResult) =>
        {
            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(resAsyncResult))
                {
                    try
                    {
                        data = ProcessResponse(XmlReader.Create(response.GetResponseStream()));
                    }
                    catch (Exception e)
                    {
                        // Exception handling
                    }
                    finally
                    {
                        response.Dispose();
                    }
                }
            }
            catch (WebException e)
            {
                // Exception handling
            }

        }, null);
    }
    catch (Exception ex)
    {
        // Handle the exception as you wish
    }
}, null);
Efran Cobisi
  • 6,138
  • 22
  • 22
0

Like Efran Cobisi said EndGetRequestStream is probably the function throwing the exception. Also a using statement will dispose the an object even if there is an exception so no need of a try finally to dispose it. But in any case you should be using the async methods, that will make the code a lot more readable and exception easier to catch. The equivalent of your code will be:

byte[] bytes = Encoding.UTF8.GetBytes(requestXml.ToString());
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "POST";
request.ContentType = "text/xml";

try
{

    using (Stream uploadStream = await request.GetRequestStreamAsync())
    {
        await uploadStream.WriteAsync(bytes, 0, bytes.Length);
        await uploadStream.FlushAsync();
    }

    using (HttpWebResponse response = (HttpWebResponse) await request.GetRequestStreamAsync())
    {
        data = ProcessResponse(XmlReader.Create(response.GetResponseStream()));
    }

}
catch (Exception e)
{
    // Exception
}
Benoit Catherinet
  • 3,335
  • 1
  • 13
  • 12