Неуловимое исключение, часть 2

Обновление. Я отправил отчет об ошибке в Microsoft Connect: https://connect.microsoft.com/VisualStudio/feedback/details/568271/debugger-halting-on-exception-thrown-inside-methodinfo-invoke

Если вы можете воспроизвести эту проблему на своем компьютере, пожалуйста, сообщите об ошибке, чтобы ее можно было исправить!


Хорошо, я провел некоторое тестирование и свел проблему к чему-то очень простому:

я. Создайте метод в новом классе, который выбрасывает исключение:

public class Class1 {
    public void CallMe() {
        string blah = null;
        blah.ToLower();
    }
}

II. Создайте MethodInfo, который указывает на этот метод где-то еще:

Type class1 = typeof( Class1 );
Class1 obj = new Class1();
MethodInfo method = class1.GetMethod( "CallMe" );

III. Оберните вызов Invoke() в блок try/catch:

try {
    method.Invoke( obj, null ); // exception is not being caught!
} catch {
}

внутривенно Запустите программу без отладчика (работает нормально).

v. Теперь запустите программу с помощью отладчика. Отладчик остановит программу, когда возникнет исключение, даже если оно помещено в обработчик catch, который пытается его игнорировать. (Даже если вы установите точку останова в блоке перехвата, она остановится до того, как достигнет ее!)

На самом деле, исключение происходит, когда вы запускаете его и без отладчика. В простом тестовом проекте это игнорируется на каком-то другом уровне, но если ваше приложение имеет какую-либо глобальную обработку исключений, оно также будет запущено там. [смотреть комментарии]

Это вызывает у меня настоящую головную боль, потому что он продолжает запускать обработчик сбоев моего приложения, не говоря уже о боли, которую он пытается отлаживать.

2 ответа

Решение

Я могу воспроизвести это на моем.NET 4 box, и вы правы - это происходит только на.NET 4.0.

Это пахнет очень как ошибка для меня, и должен идти на MS Connect. Главный облом, если это отключает ваш обработчик аварий. Похоже, неприятный способ обойти это состоит в том, чтобы обернуть вызываемый метод внутри его собственного обработчика.:-(

Однако я не могу воспроизвести одну вещь - отключить обработчик сбоя. Вот моя программа:

namespace trash {
    public class Class1 {
        public void CallMe() {
            string blah = null;
            blah.ToLower();
        }
    }

    class Program {
        static void Main(string[] args) {
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);           
            var class1 = typeof(Class1);
            var method = class1.GetMethod("CallMe");

            try {
                var obj = new Class1();
                method.Invoke(obj, null); // exception is not being caught!
            }
            catch (System.Reflection.TargetInvocationException) {
                Console.Write("what you would expect");
            }

        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
            Console.Write("it would be horrible if this got tripped but it doesn't!");
        }
    }
}

Вы не можете поймать все исключения. В вашем примере есть несколько предположений. Вы, например, предполагаете, что исключение было вызвано в вызывающем потоке. Перехват необработанных исключений в других потоках зависит от того, какие среды выполнения вы используете (console, winforms, WPF, ASP.Net и т. Д.).

Кроме того, вызовы System.Environment.FailFast() не генерируют никаких условий, которые можно обработать - процесс фактически прекращается без шансов на вмешательство.

Другие вопросы по тегам