有没有一种方法可以为WinForms .NET 3.5应用程序中的未处理异常定义操作?
注意,我意识到这里已经解决了。那篇文章讨论了.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(); } } }