【问题标题】:Global exception handler for MVVM Light applicationMVVM Light 应用程序的全局异常处理程序
【发布时间】:2012-06-05 17:15:18
【问题描述】:

我正在尝试在使用 MVVM Light Toolkit 构建的 WPF 应用程序中创建一个简单的全局异常处理程序,但我很难让它工作。

问题是视图模型中出现的异常不会被应用程序的 UnhandledException 处理程序捕获,即使我像这样为 Dispatcher 和 AppDomain 注册了一个侦听器:

private void Application_Startup(object sender, StartupEventArgs e)
{
   AppDomain.CurrentDomain.UnhandledException += DomainUnhandledException;
   DispatcherUnhandledException += App_DispatcherUnhandledException;
}

private void DomainUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
   var exception = unhandledExceptionEventArgs.ExceptionObject as Exception;
   ShowExceptionMessage(exception);
}
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
   ShowExceptionMessage(e.Exception);
   e.Handled = true;
}

我找到了描述问题点的this blog post,并使用此代码为视图模型截取了描述的解决方案:

// Throw the exception in the UI thread.
App.Current.RootVisual.Dispatcher.BeginInvoke(() => { throw new MyException(); });

但是,我希望所有异常都冒泡到全局异常处理程序,而不仅仅是那些我自己扔进 VM 中的异常。

所以问题是:是否有可能以某种方式将其他线程的异常重新抛出到一个地方的 UI 线程中?

更新:为应用程序的事件处理程序设置添加了更详细的代码。

【问题讨论】:

  • 很抱歉,在提问之前我显然没有对这个问题进行足够的调查。我测试的异常实际上是在 VM 构造函数中抛出的。 Unity 用于 DI,所以问题应该是,如何处理由 unity 创建的对象的构造函数中的异常?
  • 为了进一步解释,这就是 VM 绑定到视图的 DataContext 的方式:DataContext="{Binding MyVm, Source={StaticResource Locator}}"。定位器暴露了以下属性:public MyViewModel MyVm { get { return unityContrainer.Resolve<MyViewModel>(); } }

标签: wpf exception-handling mvvm-light


【解决方案1】:

我想我现在想通了。

问题是由于 WPF 抑制了视图数据绑定中引发的异常,并且因为我的视图模型数据绑定到视图的 DataContext(通过我的 ViewModelLocator 中的属性使用统一依赖注入器)视图模型构造中的任何异常都会被吞没。

请参阅this SO question 了解更多信息。

所以我想我只需要确保在构造函数中不会发生对应用程序正常运行能力重要的事情。

【讨论】:

  • 只有在视图可见时它们才会被抑制。如果您尝试显示视图并且视图模型的绑定属性引发了异常(假设您在调用 show 之前已经设置了数据上下文),您将无法打开窗口
【解决方案2】:

WPF 和 Windows 窗体应用程序(Application.DispatcherUnhandledException 和 Application.ThreadException)的“全局”异常处理事件仅对主 UI 线程上抛出的异常触发。您仍然必须手动处理工作线程上的异常。

AppDomain.CurrentDomain.UnhandledException 触发任何未处理的异常,但无法阻止应用程序随后关闭。

  • 也许还要检查线程池“分而治之”的风格。
  • TPL

How do I invoke a method on the UI thread when using the TPL?

【讨论】:

  • 是的,我知道 DispatcherUnhandledException 用于 UI 线程异常,而 AppDomain 的 UnhandledException 用于任何未处理的异常。问题是它们都没有捕获到我在 VM 的命令处理程序中引发的任何异常。 MVVM Light 是否为其线程提供某种“全局异常处理程序”,还是我必须将所有命令处理程序包装在一个 try-catch 块中?
  • 实际上,如果我在数据绑定命令中抛出异常,它确实会冒泡到 Dispatcher 的异常处理程序。请参阅我对这个问题的评论。
猜你喜欢
  • 2014-04-17
  • 2012-12-31
  • 2011-05-19
  • 2011-08-31
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多