在FrameWork级别捕获WPF中的exception

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

暂时忽略所有不这样做的好论据,我遇到以下情况:

如果我在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 } 

然后在我的一个VM中引发exception,处理程序按预期调用。

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

我真正想要做的是恢复,并将控制权返回给主框架VM。 (再次抛开反对这样做的动机)。

所以,做一些阅读,我决定在同一个地方为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的处理程序。

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

值得一提的是,框架中没有明确使用线程。

VS向您显示exception的原因是因为您已将其设置为相同(要么您明确地执行了此操作,要么 – 更可能 – VS中的默认配置如此)。 您可以通过Debug->Exceptions菜单控制Visual Studio在调试代码中遇到exception时所执行的Debug->Exceptions

即使你有一个捕获它,你甚至可以让它打破,这在某些情况下非常方便。

如果您没有使用multithreading,那么您应该使用DispatcherUnhandledException事件,因为它将捕获在主UI线程上未被捕获的所有内容。

快速回答我自己的问题:

这有效……

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的exception捕获有关。 请参阅Isak上面的评论。]

但是,这是一个很大的但是,如果你在VisualStudio中执行,那么你仍然会弹出VSexception通知对话框,只有当你按F5 / continue时才会调用DispatcherUnhandledExceptionHandler,之后执行将继续按照正常情况。

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