Получение необработанного исключения в отладчике VS2010, даже если исключение обработано

У меня проблема с 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 ответа

Вот ответ от 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().

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

В вашем коде, который выбрасывает исключение в код.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. */ }
Другие вопросы по тегам