有没有一种方法可以为WinForms .NET 3.5应用程序中的未处理异常定义操作?

时间:2020-03-06 14:56:34  来源:igfitidea点击:

注意,我意识到这里已经解决了。那篇文章讨论了.NET 1.1中的异常处理,同时暗示着> .NET 2.0有更好的解决方案,因此,这个问题专门针对最新的.NET版本。

我有一个Windows窗体应用程序,预计该应用程序会经常和意外地失去与数据库的连接,在这种情况下,它将自己重置为初始状态。

我已经通过自定义DBWrapper对象上的一组装饰器进行了错误日志记录,重试连接等。但是,在此之后,我想让错误落入堆栈。一旦到达顶部并且未处理,我希望将其吞下并执行我的ApplicationResetter.Reset()方法。

谁能告诉我该怎么做?

如果这是不可能的,那么至少有一种方法可以解决此问题,而不必对每个可能收到此类错误的类都引入对ApplicationResetter的依赖,并且不必实际关闭并重新启动我的应用程序(看起来很丑)?

解决方案

警告:尚不熟悉3.5,可能会有更好的答案...

...但是我的理解是,到事件到达未处理的异常处理程序时,该应用可能会死掉,如果它没有死,那么它可能已经损坏到了无论如何应该死掉了

如果我们已经在处理db-not-there的情况,并允许其他异常通过,则该应用应该死掉,因为它可能不稳定

也许Application.ThreadException事件适合需求:

static void Main()
{
    Application.ThreadException += Application_ThreadException;
    //...
 }

 static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
 {
     // call ApplicationResetter.Reset() here
 }

有" System.Windows.Forms.Application.ThreadException"事件和" System.AppDomain.CurrentDomain.UnhandledException"事件。

正如史蒂文(Steven)所述,这些将使应用程序处于未知状态。除了将可能引发异常的调用放在try / catch块中之外,实际上没有其他方法可以执行此操作。

最新的MSDN问题中对未处理的异常的相当深入的解释:
2008年9月

对于Windows Forms线程(调用Application.Run()),请在Main()的开头分配一个ThreadException处理程序。另外,我发现有必要调用SetUnhandledExceptionMode:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.Automatic);
Application.ThreadException += ShowUnhandledException;
Application.Run(...);

这是一个示例处理程序。我知道这不是我们要查找的内容,但是它显示了处理程序的格式。请注意,如果我们希望异常是致命的,则必须显式调用Application.Exit()。

static void ShowUnhandledException(object sender, ThreadExceptionEventArgs t)
{
    Exception ex = t.Exception;
    try {
        // Build a message to show to the user
        bool first = true;
        string msg = string.Empty;
        for (int i = 0; i < 3 && ex != null; i++) {
            msg += string.Format("{0} {1}:\n\n{2}\n\n{3}", 
                first ? "Unhandled " : "Inner exception ",
                ex.GetType().Name,
                ex.Message, 
                i < 2 ? ex.StackTrace : "");
            ex = ex.InnerException;
            first = false;
        }
        msg += "\n\nAttempt to continue? (click No to exit now)";

        // Show the message
        if (MessageBox.Show(msg, "Unhandled exception", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.No)
            Application.Exit();
    } catch (Exception e2) {
        try {
            MessageBox.Show(e2.Message, "Fatal error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
        } finally {
            Application.Exit();
        }
    }
}