Необязательное исключение, pt 2
Обновление: Я зарегистрировал отчет об ошибке в Microsoft Connect: https://connect.microsoft.com/VisualStudio/feedback/details/568271/debugger-halting-on-exception-thrown-inside-methodinfo-invoke#details
Если вы можете воспроизвести эту проблему на своем компьютере, пожалуйста, отсканируйте ошибку, чтобы она могла быть исправлена!
Хорошо, я провел некоторое тестирование, и я решил проблему просто:
я. Создайте метод в новом классе, который генерирует исключение:
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 {
}
IV. Запустите программу без отладчика (отлично работает).
v. Теперь запустите программу с помощью отладчика. Отладчик остановит программу, когда произойдет исключение, даже если оно завершено обработчиком catch, который пытается игнорировать его. (Даже если вы поместите контрольную точку в блок catch, она остановится, прежде чем она ее достигнет!)
Фактически, исключение происходит, когда вы запускаете его без отладчика. В простом тестовом проекте его игнорируют на каком-то другом уровне, но если ваше приложение имеет любую глобальную обработку исключений, оно также будет запущено там. [см. Комментарии]
Это вызывает у меня настоящую головную боль, потому что он продолжает запускать мой обработчик сбоя приложения, не говоря уже о болью, которую нужно попытаться отладить.
Ответы
Ответ 1
Я могу воспроизвести это в своем ящике .NET 4, и вы правы - это происходит только на .NET 4.0.
Это пахнет очень как ошибка для меня, и я должен пойти на MS Connect. Основной bummer, если это отключает ваш обработчик сбоя. Звучит как непривлекательный способ обойти это, чтобы обернуть вызванный метод внутри своего обработчика.: - (
Одна вещь, которую я не могу воспроизвести, однако, отключает обработчик аварии. Здесь моя программа:
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!");
}
}
}
Ответ 2
Вы не можете поймать все исключения. В вашем примере есть несколько предположений. Вы, например, считаете, что исключение было поднято в вызывающем потоке. Захват необработанных исключений из других потоков зависит от того, какие среды выполнения вы используете (консоль, winforms, WPF, ASP.Net и т.д.).
Кроме того, вызовы System.Environment.FailFast() не генерируют какое-либо принудительное условие - процесс эффективно завершается без каких-либо вмешательств.