WebException, созданное в приложении WinRT, которое не может быть перехвачено

Эта проблема действительно странная и ускользает от моих попыток отладки. Это происходит только при запуске приложения на планшете Surface. Это не происходит на планшете Asus или при работе в Visual Studio. В конкретном сценарии, когда включен режим полета, выдается исключение WebException, которое я абсолютно не могу поймать. Я даже не совсем уверен, что в моем коде вызывает это, потому что некоторые из моих журналов не происходят после определенного момента в коде по неизвестной причине. Я могу только предположить, что это вызвано HttpWebRequest из-за типа выдаваемого исключения, которое, по-видимому, исходит от внутреннего компонента .NET. Вот единственная отладочная информация, которую я могу получить. Это из средства просмотра событий Windows:

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)

Я действительно хотел бы предоставить больше информации об отладке, но я перепробовал все, что мог придумать, с кучей блоков try/catch повсюду и ведением журнала после большинства вызовов, некоторые из которых не выполняются. Кто-нибудь знает, что может быть причиной этого?

РЕДАКТИРОВАТЬ 1:

Основываясь на трассировках, кажется, что где-то здесь возникает исключение. Практически все заключено в блок try/catch, поэтому я не понимаю, как WebException может проскальзывать.

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
}

РЕДАКТИРОВАТЬ 2:

Я до сих пор не нашел приемлемого решения. В настоящее время я заранее проверяю тип подключения и не разрешаю коду продолжать работу, если он не подключен к WiFi, мобильной связи или Ethernet, но это не улавливает условие, когда он подключен к сети, которая не имеет подключения к Интернету. WinRT не имеет решения для проверки подключения к Интернету, и даже метод, который я использую, неудобен для работы (он просто возвращает число -- http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/d8e76732-19d3-47b3-840f-70d87c75ce9f).


person jokeefe    schedule 05.04.2013    source источник
comment
возможно, показ вашего кода поможет.., если есть исключение, есть способ его поймать.. возможно, вы пытаетесь его поймать неправильно..   -  person MethodMan    schedule 05.04.2013
comment
@DJ KRAZE Опубликован код, в котором, как мне кажется, создается исключение.   -  person jokeefe    schedule 08.04.2013
comment
неужели твой Exception Code Block действительно так выглядит..? вы не обрабатываете никаких исключений   -  person MethodMan    schedule 08.04.2013
comment
@DJ KRAZE Нет, я обрезал код перед публикацией, чтобы исключить ненужную регистрацию сообщений об ошибках и бизнес-логику.   -  person jokeefe    schedule 08.04.2013


Ответы (3)


Пробовали ли вы обрабатывать Application.UnhandledException< /а>?

Добавьте обработчик события к событию в конструкторе класса App:

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

В обработчике событий вы можете зарегистрировать исключение, и пометка обрабатывается, чтобы предотвратить закрытие/сбой приложения:

void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    // log e.Exception details for investigation
    e.Handled = true;
}
person Damir Arh    schedule 05.04.2013

Проблема, вероятно, связана с необработанным исключением, вызванным вашим обратным вызовом; высоки шансы, что обратный вызов выполняется асинхронно в потоке, отличном от того, который вызвал начальный request.BeginGetRequestStream, и поэтому вы не перехватываете его во внешнем блоке try/catch. Вы сможете решить эту проблему, поместив все содержимое обратного вызова в блок try/catch, то есть:

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);
person Efran Cobisi    schedule 07.09.2013

Как сказал Эфран Кобиси, EndGetRequestStream, вероятно, является функцией, вызывающей исключение. Кроме того, оператор using будет удалять объект, даже если есть исключение, поэтому нет необходимости пытаться окончательно его удалить. Но в любом случае вы должны использовать асинхронные методы, которые сделают код намного более читабельным, а исключения легче перехватывать. Эквивалентом вашего кода будет:

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
}
person Benoit Catherinet    schedule 11.09.2013