在WPF中捕获框架级别的异常

11 浏览
0 Comments

在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异常中恢复吗?

可能有必要提到的是,在该框架中没有显式使用线程。

0
0 Comments

在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的异常。

0
0 Comments

在WPF中捕获异常的问题是由于在Visual Studio中的设置导致的。可以通过Debug->Exceptions菜单来控制在调试代码中遇到异常时Visual Studio的行为。如果不使用多线程,则可以使用DispatcherUnhandledException事件来捕获在主UI线程上未捕获的所有异常。

0