WinForm "global" 捕获 MDI 子窗体的异常 "only"

WinForm "global" catch exception for MDI child forms "only"

我有一个 MDI 父/子应用程序。
在 Program.cs 文件中,我有一个用于 ThreadException 和 UnhandledException 的全局异常处理程序。

那些工作正常。

当我在全局级别遇到未处理的异常时,我在 UnhandledException 处理程序中调用 Environment.Exit(1) 来关闭应用程序,因为我不知道应用程序的当前状态。

在子表单中,我 "normally" 将以下内容添加到事件处理程序。

try
{
    // Some Code
}
catch (Exception ex)
{
    HandleException(ex);
    MessageBox.Show("Some message");
    this.Close();
}

我想知道是否有一种方法可以为我所有的子窗体添加一个全局异常处理程序(我确实有一个它们继承自的基本窗体),它可以捕获异常并关闭子窗体而不关闭整个窗体申请。
这样,如果开发人员 "forgot" 在事件上添加 try catch 块,就不会破坏整个应用程序。

正如我在评论中所说的那样,我不太喜欢您的方法,尤其是您捕获最一般的异常的情况。

The message will only partially help you fix the problem. A crash can help you completely fix the problem, including call stack, objects on the heap, CPU registers etc. Just learn How to take a crash dump and analyze it. By closing an MDI form, you ignore the fact that the data of your application may be in an invalid state

但是好吧,那是编码风格,也许不应该在这里讨论。

你能做的就是Aspect Oriented Programming (APO) [Wikipedia]。方面是适用于代码的多个部分的东西,您不想在任何地方显式地实现它。

您将一个方面实现为代码,然后在配置文件中定义您希望应用该代码的位置,例如按照命名约定。

奇迹发生在编译时。编译正常代码后,中间代码编织器 (IL-weaver) 会修改 IL 代码并在各处插入切面。

您需要一个像 PostSharp (commercial) or AfterThought (free). PostSharp even has examples for exception handling 这样的库,可以很容易地采用它来显示消息框。

第一次尝试时需要费些心思,因此在将该概念应用到您的代码之前,请务必遵循一些教程。

我同意这通常是个坏主意,但如果您的全局异常处理程序有一个 "sender" 对象,您可以尝试使用 sender.GetType() 来获取对象的类型。您可以通过说 if (sender.GetType().IsSubclassOf(typeof (BaseClass))) { // then do something } 来查看它是否继承自您的基本形式。

如果发送者是子窗体的子控件(而不是窗体本身),那么您可能需要使用辅助方法向上走几层祖先以找到父窗体(例如:发送者可能是一个文本框,sender.Parent 可能是一个面板,sender.Parent。父级可能是表单)。您可以递归地检查父级,直到父级为空,或者父级派生自您的基 class.

您还可以循环遍历 MdiParent 窗体的 MdiChildren 以查看是否有任何一个是导致异常的窗体。那么你就不需要从基础继承 class.

此外,在 ThreadException 的情况下,如果您在即发即弃类型的线程中有一些匿名方法,这可能不起作用...

我只在一个项目中使用全局异常处理,我好像记得它在调试模式下不能正常工作,因为你得到的是 Visual Studio 异常助手,所以我没有测试这个的快速方法 - 只需将其视为一般 "pseudocode" 推荐...