我有一个MDI父/子应用程序 在Program.cs文件中,我有一个ThreadException和UnhandledException的全局异常处理程序。
那些工作正常。
当我在全局级别获得未处理的异常时,在UnhandledException处理程序内部,我调用Environment.Exit(1)来关闭应用程序,因为我不知道应用程序的当前状态。
在子表单中,我“通常”将以下内容添加到事件处理程序中。
try
{
// Some Code
}
catch (Exception ex)
{
HandleException(ex);
MessageBox.Show("Some message");
this.Close();
}
我想知道是否有一种方法可以为我的所有子表单添加一个全局异常处理程序(我确实有一个继承自的基本表单),它可以捕获异常并关闭子表单而不关闭整个应用程序。
这样,如果开发人员“忘记”在事件上添加try catch块,它就不会轰炸整个应用程序。
答案 0 :(得分:0)
正如我在评论中已经说过的那样,我并不喜欢你的方法,特别是你正在捕捉最普遍的例外情况。
该消息只能部分帮助您解决问题。崩溃可以帮助您完全解决问题,包括调用堆栈,堆上的对象,CPU寄存器等。只需学习How to take a crash dump并进行分析。通过关闭MDI表单,您可以忽略应用程序数据可能处于无效状态的事实
但是好的,这是编码风格,也许这不应该在这里讨论。
你可以做的是Aspect Oriented Programming (APO) [Wikipedia]。方面适用于代码的几个部分,您不希望在任何地方明确地实现它。
您将一个方面实现为代码,然后在配置文件中定义您希望应用该代码的位置,例如:通过命名惯例。
魔术发生在编译时。编译正常代码后,中间代码weaver(IL-weaver)修改IL代码并在任何地方插入方面。
您需要一个类似PostSharp(商业)或AfterThought(免费)的库。 PostSharp甚至有examples for exception handling,可以很容易地用来显示消息框。
第一次尝试时需要一些精神上的弯曲,所以在将conceopt应用到代码之前,请务必遵循一些教程。
答案 1 :(得分:0)
我同意这通常是一个坏主意,但如果你的全局异常处理程序有一个“sender”对象,你可以尝试使用sender.GetType()
来获取对象的类型。您可以通过说if (sender.GetType().IsSubclassOf(typeof (BaseClass))) { // then do something }
来查看它是否继承自您的基本表单。
如果发件人是子表单的子控件(而不是表单本身),那么您可能需要使用帮助程序方法走几级祖先来查找父表单(例如:发件人可能是textbox,sender.Parent可能是一个面板,sender.Parent.Parent可能是表单)。您可以递归检查父项,直到Parent为null,或父项派生自您的基类。
您还可以遍历MdiParent表单的MdiChildren,看看是否有任何表单导致异常。那么你就不需要继承基类了。
另外,在ThreadException的情况下,如果在fire-and-forget类型的线程中有一些匿名方法,这可能不起作用......
我只在一个项目中使用全局异常处理,我似乎记得它在调试模式下无法正常工作,因为你得到了Visual Studio异常助手,所以我没有快速测试这个 - 只是将其视为一般性的“伪代码”推荐......