应用程序级别的全局错误处理?

4

我有一个WPF表单,里面有几个按钮,每个按钮都有错误处理代码:

try {bla bla} 
catch(Exception e){
  more bla
}

有没有办法在应用程序级别或其他地方设置一些东西,以便捕获所有未捕获的错误并显示一些通用消息/记录错误?现在我必须为每个按钮创建处理程序,以避免代码崩溃。这是一个内部应用程序,因此只需显示从下面抛出的消息即可。之后,应用程序将等待下一个按钮点击,因此之后不需要执行任何操作。
现在有很多重复的代码,想知道是否有某种方法可以合并它们,并仅处理特定错误的特定情况。
问候 Gert-Jan

6
如果我是你,我会先尝试修复所有异常的根本原因。 - Joe
@Furqan,你有相关链接吗? - gjvdkamp
@Joe,这主要是一些愚蠢的问题,比如在指定输出文件之前点击“go”等。它是内部的,所以我真的不想使用Storyboard等等。如果出了问题,只需不崩溃就行了,而不必编写所有这些不同的处理程序。 - gjvdkamp
@gjvdkamp:请查看我的答案以获取解决方案。 - Daniel Hilgarth
@gjvdkamp - 是否应该抛出异常还有讨论的余地。对于这种有状态的事情,我会使用“状态转换”异常(即当您不应该从A到B时),但是它应该与实际防止发生这种情况的代码相平衡(即如果用户不应该从A -> B,不要允许他们这样做)。 - Joe
显示剩余3条评论
5个回答

12

谢谢你的建议。它能捕获错误,但是有没有办法在此后停止代码运行呢?现在即使错误被捕获了,代码仍会崩溃。 - gjvdkamp
不应该这样做。否则,这个事件将是无用的。你的代码肯定有一些错误。看一下提供的链接。 - Daniel Hilgarth
不过,你知道WPF上的ThreadException等价物是什么吗?也许我也应该捕获它。 - gjvdkamp
请使用Application.DispatcherUnhandledException - Daniel Hilgarth
尝试在DispatcherUnhandledException中使用e.Handled=true。 - Kishore Kumar
显示剩余2条评论

2

将以下内容添加到你的Global.asax文件中:

protected void Application_Error(object sender, EventArgs e) {
    Exception currentException = Server.GetLastError();

    // your handling code goes here ...

    Server.ClearError();
}

我已经有一段时间没有做这种事情了,但是... 这感觉不太线程安全。 - Joe
抱歉,这是一个 WPF 应用程序,我没有提到。 - gjvdkamp

1

您可以订阅AppDomain.UnhandledException事件(请参见MSDN)来实现此功能。理想情况下,这应该在启动应用程序时发生。您可以通过AppDomain.Current找到正在执行的AppDomain。


AppDomain.CurrentDomain.UnhandledException += CatchAllHandler; 就是这样,谢谢! - gjvdkamp

0

答案取决于你所使用的平台。在 Web 应用程序中,你可以在 Global Asax 中绑定 Application_Error 事件。在 WCF 中,你可以将一个类型为 System.ServiceModel.Dispatcher.IErrorHandler 的错误处理程序注入到 WCF 栈中;在表单应用程序中,你可以绑定 ThreadException 事件。

在某些情况下,使用它可能是一个好主意,因为可以防止向用户显示异常详细信息,但同时也表明了某种关于异常处理的懒散态度。我已经使用 WCF 错误处理程序将领域异常转换为 HTTP 状态码,这很简单。无论它是否是一种良好的实践,我并不知道。对于 ASP.NET 应用程序,值得注意的是还有 elmah,可通过 NuGet 获得。

还可以编写一个简单的异常处理程序,通过发送例程作为FuncAction来重复尝试/捕获块,如下所示

    var eh = new ExceptionHandler();

    eh.Process ( () => throw new SillyException());

使用类 ExceptionHandler

    class ExceptionHandler 
    { 
        public T Process(Func<T> func()) 
        {
           try { return func(); }
           catch(Exception ex) { // Do stuff }
        }

        public void Process(Action a) 
        { 
            try { action() }
            catch(Exception ex) { // Do stuff }
        }
    }

-3
如果是WinForms应用程序,您可以将Application.Run()调用封装在try catch语句中,但我真的不建议这样做,您只应该在绝对必要时使用try catch,并在完全依赖catch之前尽可能处理异常。
我知道这种方法可行,因为我曾经临时使用它来清理应用程序崩溃的情况。

-1:这样做不行,因为之后应用程序将无法正常工作。 - Daniel Hilgarth
这是正确的,但这就是为什么我说我不太建议这样做的原因。它只是作为一个通用的捕获所有异常的方式,但这实际上是一种懒惰而不负责任的做法。 - hdougie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接