Как я могу заставить WinForms перестать молча игнорировать необработанные исключения? - PullRequest
32 голосов
/ 27 сентября 2011

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

Короче говоря, в WinForms, будучи таким же крутым, как и в случае возникновения исключения, библиотека WinForms игнорирует его. Сообщение JIT «необработанное исключение произошло» не выдается, оно просто прекращает обработку текущего события и возвращается в графический интерфейс.

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

Чтобы увидеть это в действии, я создал совершенно новое приложение WinForms и ввел следующий код:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        string blah = null;
        blah.Trim();
    }
}

Нажмите F5, и форма загрузится без каких-либо ошибок, даже если создается нулевая ссылка.

Затем я попытался перейти к своему Program.cs методу main и добавить к нему Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);. Тем не менее, моя форма загружается без каких-либо ошибок.

Несмотря на то, что я знаю, что могу сказать VS прервать во всех исключениях, я считаю эту ситуацию действительно плохой. Это вызывает действительно странные проблемы, которые трудно отладить в производственном процессе, и, поскольку это внутренний инструмент, я действительно хочу иметь его, чтобы он действительно выводил ошибки при возникновении исключения, а не игнорировал его молча.

Кто-нибудь знает, как это сделать?


Обновление: Просто чтобы обновить информацию, которую я узнал из комментариев.

Похоже, что это 64-битная проблема с Windows, как я узнал из этого вопроса , который я не видел до публикации. В этом вопросе он указал на сообщение об ошибке Microsoft об этом, в котором было сказано:

Здравствуйте,

Эта ошибка была закрыта как «Внешняя», потому что это поведение связано с тем, как x64-версия Windows обрабатывает исключения. Когда исключение пользовательского режима пересекает переход ядра, 64-разрядные версии Windows не позволяют распространению исключения. Поэтому подключенные отладчики не знают о том, что произошло исключение, в результате чего отладчик не смог сломать необработанное исключение.

К сожалению, когда команда Visual Studo ничего не может сделать для решения этой проблемы, это результат проектирования операционной системы. Все отзывы по этой проблеме следует адресовать команде Windows; однако команда Windows считает это «правильным» дизайном операционной системы и считает поведение x86 «неправильным».

С наилучшими пожеланиями, Visual Studio Debugger

При этом сборки, не запускаемые через Visual Studio (или использующие Ctrl + F5 для запуска), по-видимому, показывают окно сообщения об исключении JIT EXCEPT , если в вашем Program.cs есть следующий код:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);

Этот код заставит Windows игнорировать исключение.

Однако, если вы (вместо этого) подпишетесь на событие Application.ThreadException, не только ваши исключения будут обнаружены, но отладчик Visual Studio будет прерывать необработанные исключения!

Ответы [ 4 ]

16 голосов
/ 27 сентября 2011

В основной функции вашего Program.cs вы также должны убедиться, что вы завернули свой вызов, чтобы открыть форму в try / catch.Дополнительно используйте AppDomain.UnhandledException для перехвата исключений.Мы также добавляем Application.ThreadException тоже.

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

static void Main()
{
    try
    {
        System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        System.Windows.Forms.Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(OnGuiUnhandedException);
        AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;

        var form = new MainForm();
        form.ShowDialog();
    }
    catch (Exception e)
    {
        HandleUnhandledException(e);
    }
    finally
    {
        // Do stuff
    }
}

private static void HandleUnhandledException(Object o)
{
    // TODO: Log it!
    Exception e = o as Exception;

    if (e != null)
    {

    }
}

private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs e)
{
    HandleUnhandledException(e.ExceptionObject);
}

private static void OnGuiUnhandedException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
    HandleUnhandledException(e.Exception);
}
7 голосов
/ 27 сентября 2011

Попробуйте следующее.

  • Обработка исключений в основной точке входа приложения.
  • Кроме того, управляйте необработанными исключениями потоков, используя ThreadExceptionEventHandler

Это фрагмент кода:

[STAThread]
public static void Main(string[] args)
{
    try
    {
        Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
        //your program entry point
    }
    catch (Exception ex)
    {
       //manage also these exceptions
    }
}

private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
    ProcessException(e.Exception);
}
4 голосов
/ 27 сентября 2011

Простое исправление - не запускаться под отладчиком.

По какой-то причине отладчик маскирует исключение.Если вы запустите приложение в обычном режиме (Ctrl + F5), вы получите обычное «Необработанное исключение произошло в вашем приложении ... Продолжить / Выйти?»диалоговое окно.

0 голосов
/ 15 октября 2014

Часто сталкиваясь с этим и выявляя проблему, связанную с 64-битной ОС и событием Form.Load, я всегда просто стараюсь выполнять все свои функции запуска в событии Form.Shown. Для всех практических целей это одно и то же (кроме нескольких редких, исключительных обстоятельств), и сообщение JIT создается в событии Shown.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...