Рассмотрите следующее простое заявление: форма окон, созданная "новым приложением Windows C#", упорядочивает в VS, который был изменен следующим способом:
public static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try
{
Application.Run(new Form1());
}
catch (Exception ex)
{
MessageBox.Show("An unexpected exception was caught.");
}
}
Form1.cs содержит следующие модификации:
private void Form1_Load(object sender, EventArgs e)
{
throw new Exception("Error");
}
Если я нажимаю F5 in IDE, то, как я ожидаю, я вижу, что окно сообщения говорит, что исключение было поймано и выходы приложения.
Если я перехожу к Отладке (или Выпуск) / мусорное ведро и запускаю исполняемый файл, я вижу окно "Unhandled exception" стандарта, подразумевая, что мой обработчик исключений не работает.
Очевидно, это имеет некоторое отношение к исключению, бросаемому от другого потока то Приложение. От выполненный называют. Но вопрос остается - почему поведение отличается в зависимости от того, было ли приложение запущено от IDE или из командной строки? Что лучшая практика должна гарантировать, чтобы никакие исключения не оставались необработанными в приложении?
Обычно Application.ThreadException обрабатывает исключение в событии Load. Вы получите ThreadExceptionDialog, который предлагает варианты выхода и продолжения.
Но не тогда, когда подключен отладчик. В этом случае предложение catch в цикле сообщений, которое отображает диалоговое окно, намеренно отключено.Это необходимо, потому что было бы очень трудно устранять неполадки в исключениях, если это диалоговое окно появляется при отладке программы. Если этот уловитель больше не активен, ваше предложение catch в методе Main () теперь получает шанс на исключение.
Вы можете сделать это согласованным, используя Application.SetUnhandledExceptionMode () в методе Main (). Вы не должны, исключения действительно трудно отлаживать, если вы это сделаете. Если вы хотите настроить обработку исключений для потока пользовательского интерфейса, вам следует зарегистрировать собственный обработчик Application.ThreadException:
if (!System.Diagnostics.Debugger.IsAttached)
Application.ThreadException += myThreadException;
Для перехвата необработанных исключений в рабочих потоках требуется обработчик AppDomain.UnhandledException. Они не подлежат восстановлению.
Также будьте осторожны с ошибкой в 64-битной Windows, исключения в событии Load проглатываются без диагностики при подключении отладчика. Включите режим AnyCPU, чтобы избежать этой ловушки.
В дополнение к перехвату любых исключений, возникающих внутри метода Main
, вы также должны обрабатывать исключения AppDomain.CurrentDomain.UnhandledException
и Application.ThreadException
.
Не уверен, почему поведение отличается с подключенным отладчиком и без него.