Получение необработанного исключения в отладчике VS2010, даже если исключение обработано - PullRequest
8 голосов
/ 11 апреля 2011

У меня проблема с VS2010, когда отладчик останавливается с необработанным исключением.Тем не менее, исключение определенно обрабатывается.Фактически, если я добавлю код в блок catch, я нажму его, когда нажму F5.В Отладке -> Исключения, я определенно не установил флажок «Брошенный», поэтому у IMO нет абсолютно никакой причины для всплывающего диалогового окна необработанного исключения ...

Я могуне размещать точный код, но скоро будет работать над образцом.Основная идея, лежащая в основе кода обидного кода, состоит в том, что у меня есть поток, который общается с аппаратным обеспечением, и если у меня возникает ошибка при разговоре с ним, я выдаю HardwareException.Поток запускается с BeginInvoke, и исключение перехватывается в обработчике обратного вызова, когда я вызываю EndInvoke.

Когда в отладчике выбрасывается исключение, я получаю окно с сообщением «HardwareException не обработано»по коду пользователя ". Но это !!!

РЕДАКТИРОВАТЬ - Ну, это сводит меня с ума. У меня есть пример кода, который представляет код, который у меня есть в приложении, и выглядитэто:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Messaging;
using System.Threading;

namespace ConsoleApplication1
{
    public class HardwareException : ApplicationException
    {
        public HardwareException( string message) : base(message) {}
    }

    class Program
    {
        delegate void HardwareTestDelegate();

        static void Main(string[] args)
        {
            HardwareTestDelegate d = new HardwareTestDelegate( HardwareTestThread);
            d.BeginInvoke( HardwareTestComplete, null);
            while( true);
        }

        static void HardwareTestThread()
        {
            throw new HardwareException( "this is a test");
        }

        static void HardwareTestComplete( IAsyncResult iar)
        {
            try {
                AsyncResult ar = (AsyncResult)iar;
                HardwareTestDelegate caller = (HardwareTestDelegate)ar.AsyncDelegate;
                caller.EndInvoke( iar);
            } catch( Exception ex) {
                Console.WriteLine( "Should see this line without getting an unhandled exception message in the IDE");
            }
        }
    }
}

Я выбрасываю свое HardwareException из потока и затем обрабатываю исключение при вызове EndInvoke. Я думаю, Мерфи был прав, потому что когда я запускаю этот пример кода, он делает то, что я ожидаю -т.е. в IDE не появляется сообщение об ошибке необработанного исключения!

Ответы [ 2 ]

2 голосов
/ 31 мая 2011

Вот ответ от Microsoft, дело 111053102422121. Аллен Венг пишет следующее:

Анализ:

Для вашей информации, CLR повторно сгенерирует исключениевнутри обратного вызова при вызове EndInvoke ().Ниже приведена упрощенная версия EndInvoke ():

public object EndInvoke(IAsyncResult asyncResult)
{
    using (new MultithreadSafeCallScope())
    {
        ThreadMethodEntry entry = asyncResult as ThreadMethodEntry;
         ............
        if (entry.exception != null)
        {
            throw entry.exception;
        }
     }
}

Исключение будет обрабатываться в функции обратного вызова или в асинхронном методе, если предоставляется обработчик исключения.Вот как это работает без отладчика.

Когда вы запускаете его в VS.NET, кажется, что отладчик проверяет только наличие обработчика исключений в асинхронном методе.Если такого обработчика нет, отладчик подумает, что исключение не обработано, и выдаст сообщение об ошибке, уведомляющее вас об этом.

Предложение:

Приложение должно работать должным образом при запускеэто одиноко.Если сообщение об ошибке раздражает вас при отладке, вы можете отключить его, сняв флажок «Необработанный пользователь» для «Исключения времени выполнения общего языка» в диалоговом окне «Исключения» («Отладка | Исключения» или нажмите CTRL + ATL + E).Или вы можете добавить try / catch в асинхронный метод.В последнем случае исключение устанавливается равным нулю и не будет переброшено в EndInvoke ().

0 голосов
/ 17 января 2013

У меня такая же проблема, поэтому я опубликую этот возможный обходной путь для потомков:

В вашем коде, который выбрасывает исключение в код .NET (HardwareTestThread () в приведенном выше примере), перехватывает выбрасываемое исключение и заключает его в какой-то эзотерический тип исключения .NET, для которого можно отключить необработанный »в диалоге« Отладка> Исключения ». В моем случае мне нужно было разрешить IOException распространяться через некоторый код .NET обратно в мой код, поэтому я просто перехватил IOException и поместил в исключение AppDomainUnloadedException, прежде чем позволить ему распространяться через код .NET обратно в мой блок catch. Я выбрал AppDomainUnloadedException, поскольку необработанный пользователь по умолчанию не отмечен для него и находится в сборке System.dll, поэтому он уже был импортирован в мой проект, хотя любое исключение должно работать, если вы отключите опцию «пользовательский необработанный» и вам все равно, что в будущем отладчик не будет работать с этим типом исключения.

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

public override int Read(byte[] buffer, int offset, int count)
{
    try { return innerStream.Read(buffer, offset, count); }
    catch (IOException ex) { throw new AppDomainUnloadedException("Exception from innerStream: " + ex.Message, ex); }
}

А вот мой код, где я перехватываю его на другой стороне .NET-кода, через который он должен был распространяться:

try { bytesRead = sslStream.Read(buffer, offset, count); }
catch (Exception ex) { /* ex handled here. */ }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...