Неуловимое исключение, часть 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() не генерируют никаких условий, которые можно обработать - процесс фактически прекращается без шансов на вмешательство.