2015-09-07 2 views
-1

Я испытал следующее. В большом приложении, которое показывает дочернюю форму MDI, исключение в дочерней форме также закрывает родительскую форму.WinForms: Почему Dispose вызывается из RunMessageLoopInner?

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

throw new ApplicationException("test"); 

Если я ставлю точку останова в основной форме (родительский MDI) Dispose метод

protected override void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     if (components != null) 
     { 
      components.Dispose(); 
     } 
    } 
    base.Dispose(disposing); 
} 

я получаю следующий вызов в стек

myApp.dll!myForm.Dispose(bool disposing) 
System.dll!System.ComponentModel.Component.Dispose() 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadWindows.Dispose() 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.DisposeThreadWindows() 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.Dispose(bool postQuit) 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reasion, System.Windows.Forms.ApplicationContext context) 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reasion, System.Windows.Forms.ApplicationContext context) 
System.Windows.Forms.dll!System.Windows.Forms.Application.Run() 

с утилизацией true.

После этого исключение, которое я хочу, чтобы поймать действительно поймал, как и ожидалось в ИВК заявлении примерки поймать, но затем МДИ родительская форма уже закрыта (почему?).


Вот некоторый код, показывающий, как работает моя верхний уровень примерки загвоздка:

public class MainApplication 
{ 
    [STAThread] 
    static void Main(string[] args) 
    { 
     Application.ThreadException += MyThreadExceptionHandler; 
     try 
     { 
      OurMain(args); 
     } 
     catch(Exception ex) 
     { 
      MessageBox.Show(ex.Message + "\n" + ex.StackTrace, "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); 
     } 
    } 

    private static void MyThreadExceptionHandler(object sender, ThreadExceptionEventArgs e) 
    { 
     MessageBox.Show(e.Exception.Message + "\n" + e.Exception.StackTrace, "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); 
    } 

    private static void OurMain(string[] args) 
    { 
     //run the application 
    } 

} 

С моим вопросом здесь я ищу стратегии для решения этой проблемы и узнать, почему родительскую форму MDI закрывается (и, наконец, препятствует ее закрытию).

То, что я думаю, что я знаю, до сих пор:

  • Я думаю, это не проблема многопоточности (. Кстати я также обрабатывать ThreadException событие и ничего не получить там), потому что я могу поймать исключение в пользовательском интерфейсе нить.

Примечание: Я задал вопрос очень общим образом. Скажите, пожалуйста, какая информация будет актуальна для вас, чтобы иметь возможность ответить на вопрос.


решение в моем конкретном случае:

В моем случае решение было не только обрабатывать Application.ThreadException но также использовать другой вариант, как описано в this answer. В моем случае обработка Dispatcher.CurrentDispatcher.UnhandledException выполнила эту работу. Application.ThreadException кажется, работает только для чистых WinForms, но я инкапсулировал веб-представление, и привязка к веб-просмотру вызвала исключение, и Application.ThreadException не отреагировал на это.

+0

В 'program.cs' подключите [Application.ThreadException] (https://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception (v = vs.110).) .aspx) Событие и принять меры оттуда ... –

+0

@Idle_Mind: Как можно прочитать в вопросе, я обрабатываю это событие ... – Sjoerd222888

+0

Извинения ... у вас есть: _after исключение, которое я хочу поймать, действительно поймано как ожидается на верхнем уровне утверждения try-catch, но затем основная форма уже удалена. Где этот try/catch? Можете ли вы показать этот код? –

ответ

0

При возникновении ошибки исключение «пузырится» по иерархии кода, пока оно не будет поймано (с помощью Try/Catch), или оно достигнет вершины.

Когда он достигает вершины (в отладке) приложение просто закрывается - закрытие любых открытых форм.

Если вы запустите.exe вы увидите стандартное сообщение: «Необработанное исключение произошло в вашем приложении». с кнопками Continue/Quit.

Способ справиться с этим - использовать блоки Try/Catch для обнаружения ожидаемых ошибок.


За исключением, чтобы добраться до основной функции верхнего уровня будет уже клокотало вверх мимо вашей формы вызывает форму, чтобы быть утилизированы (как объект формы больше не находится в области видимости). Форма либо удаляется кодом экземпляра формы, либо сборщиком мусора. Все это является частью автоматизированной очистки памяти.

+0

, пожалуйста, прочитайте вопрос, прежде чем отправлять ответ ... Хотя все утверждения правильны, я не вижу отношения к вопросу (за исключением того, что оба содержат слово «исключение»). – Sjoerd222888

+0

@ Sjoerd: Это был вопрос: «Я ищу стратегии для решения проблемы и узнаю, почему форма закрывается (и, наконец, препятствует ее закрытию). Мой ответ полностью уместен для вопроса. Если неясно то я могу уточнить. – Ulric

+0

Я отредактировал мой вопрос, возможно, он был недостаточно ясен. – Sjoerd222888