在FrameWork级别捕获WPF中的异常

时间:2011-01-07 13:17:30

标签: c# wpf exception-handling c#-4.0

我正在开发一个轻量级的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;
  // log exception
}

然后在我的一个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;
  // log exception
}

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

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

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

可能很重要的是,框架中没有明确使用线程。

2 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分: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异常通知对话框,只有按F5 / continue才会调用DispatcherUnhandledExceptionHandler,之后执行将按照正常情况继续执行。

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