在WPF中捕获框架级别的异常
在WPF中捕获框架级别的异常
我正在开发一个轻量级的WPF MVVM框架,并希望能够捕获未处理的异常,并在理想情况下从中恢复。
暂时忽略所有不做此操作的好理由,我遇到了以下情况:
如果我在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; // 记录异常 }
然后在我的一个VM中引发异常,处理程序会按预期调用。
到目前为止都很好,但问题在于我无法通过这种方法进行恢复,我能做的只是记录异常,然后让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; // 记录异常 } void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs args) { args.Handled = true; // 实施恢复 }
问题在于,一旦我为this.DispatcherUnhandledException注册了处理程序,两个事件处理程序都不会被调用。因此,注册DispatcherUnhandledExceptionHandler会以某种方式停用AppDomain.CurrentDomain.UnhandledException的处理程序。
有人有办法捕获和从未处理的VM异常中恢复吗?
可能有必要提到的是,在该框架中没有显式使用线程。
在WPF中,捕获异常的问题出现的原因是在Visual Studio中执行时,仍然会弹出VS异常通知对话框,只有在按下F5/继续后,才会调用DispatcherUnhandledExceptionHandler,并且执行将会继续正常进行。
解决方法是在App.xaml.cs文件中重写OnStartup方法,在其中注册Application.Current.DispatcherUnhandledException事件的处理程序。然后,在DispatcherUnhandledExceptionHandler方法中,将args.Handled设置为true,以表示异常已经处理,并且在此实现恢复操作。这样,在直接从命令行或Windows资源管理器运行编译后的二进制文件时,处理程序将会按预期地被调用,而不会有任何中间弹窗出现。
完整代码如下:
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的异常。