2011-01-07 129 views
3

我正在开发一个轻量级WPF MVVM框架,并希望能够捕获未处理的异常,并从中理想地恢复。在框架级别捕获WPF异常

暂时忽略所有的很好的理由不这样做,我会遇到以下情况:

如果我的App.xaml.cs的OnStartup方法内注册AppDomain.CurrentDomain.UnhandledException处理程序,如下...

App.xaml.cs:

protected override void OnStartup(StartupEventArgs e) 
{ 
    AppDomain.CurrentDomain.UnhandledException += new 
    UnhandledExceptionEventHandler(this.AppDomainUnhandledExceptionHandler); 

    base.OnStartup(e); 
} 


void AppDomainUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs ea) 
{ 
    Exception e = (Exception)ea.ExceptionObject; 
    // log exception 
} 

,然后我的虚拟机的一个内引发异常,如预期的处理程序被调用。

到目前为止,除了使用这种方法无法恢复的事实之外,我所能做的就是记录异常,然后让CLR终止应用程序。

我真正想要做的是恢复,并返回到主框架虚拟机的控制。 (再次摒弃这样做的动机)。

所以,做一些阅读,我决定在同一个地方登记为AppDomain.CurrentDomain.UnhandledException的事件处理程序,这样的代码现在看起来是这样的......

protected override void OnStartup(StartupEventArgs e) 
{ 
    AppDomain.CurrentDomain.UnhandledException += 
    new UnhandledExceptionEventHandler(this.AppDomainUnhandledExceptionHandler); 

    this.DispatcherUnhandledException += 
    new DispatcherUnhandledExceptionEventHandler(DispatcherUnhandledExceptionHandler); 

    base.OnStartup(e); 
} 

void AppDomainUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs ea) 
{ 
    Exception e = (Exception)ea.ExceptionObject; 
    // log exception 
} 

void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs args) 
{ 
    args.Handled = true; 
    // implement recovery 
} 

的问题是一旦我为this.DispatcherUnhandledException注册处理程序,无论是否调用了事件处理程序。因此,注册DispatcherUnhandledExceptionHandler以某种方式停用AppDomain.CurrentDomain.UnhandledException的处理程序。

有没有人有办法从未处理的VM异常中捕获和恢复?

提到在框架中没有明确使用线程可能很重要。

回答

5

VS向你展示异常的原因是因为你已经将它设置为这样(要么你明确地这样做了 - 或者更有可能 - VS中的默认配置就像这样)。您可以通过Debug->Exceptions菜单控制Visual Studio在调试代码中遇到异常时的操作。

即使您有一个在某些情况下非常方便的捕捉,您甚至可以让它突破。

如果你不使用多线程,那么你应该罚款DispatcherUnhandledException事件,因为它会捕获在主UI线程上捕获的所有东西。

+0

谢谢Isak,知道我会捕获所有可能产生的异常是很重要的。 – 2011-01-07 19:11:44

2

一个快速的回答我自己的问题:

这工作...

App.xaml.cs:

protected override void OnStartup(StartupEventArgs e) 
{ 
    Application.Current.DispatcherUnhandledException += 
    new DispatcherUnhandledExceptionEventHandler(DispatcherUnhandledExceptionHandler); 

    base.OnStartup(e); 
} 

void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs args) 
{ 
    args.Handled = true; 
    // implement recovery 
    // execution will now continue... 
} 

[编辑:下面我的评论有什么与实现,但是我的具体IDE(Visual Studio)配置相对于由IDE捕获异常。请参阅上面的Isak的评论。]

但是,它是一个很大的但是,如果你从VisualStudio中执行,那么你仍然会弹出VS异常通知对话框,而DispatcherUnhandledExceptionHandler只会在你按F5/continue时被调用,之后执行将按照正常进行。

如果您直接运行编译后的二进制文件,即从命令行或通过Windows资源管理器运行,那么该处理程序将按照您的预期调用,而无需任何中间弹出窗口。