繁体   English   中英

WPF-在SimpleMVVM messagebus执行的代码中捕获异常

[英]WPF - Catch exceptions in code executed by SimpleMVVM messagebus

我正在使用SimpleMVVM框架构建WPF应用程序,但是在捕获异常方面遇到了麻烦。 我使用SimpleMVVM的MessageBus将消息发送到另一个视图模型。 一切正常,但我注意到messagebus执行的代码中引发的异常被抑制了。 到目前为止,这是我得到的:

我的MainWindow包含一个在MainWindowViewModel上触发TempCommand的按钮。 该命令依次调用Test方法(如下所示),该方法使用SimpleMVVM的MessageBus发送通知消息。

private void Temp()
{
    SendMessage("Temp", new NotificationEventArgs());
}

我的MainWindow也包含带有内容的Frame 此内容的ViewModel CustomerViewModel已注册为在其构造函数中接收以下通知:

public CustomerDetailsViewModel(ICustomerServiceAgent agent)
{
    RegisterToReceiveMessages("Temp", Temp);
}

Temp方法只是引发异常:

private void Temp(object sender, NotificationEventArgs args)
{
    throw new NotImplementedException("Somewhere, something horrible happened");
}

在调试应用程序时,我清楚地看到Temp方法被调用,并且引发了异常。 但是由于某种原因,仅此而已。 该应用程序不受影响,并且我的异常捕获代码没有意识到该异常。

我通过两种方式捕获异常。 首先是通过处理Dispatcher上的事件:

<Application x:Class="MyApp"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml"
             DispatcherUnhandledException="App_DispatcherUnhandledException">

后面的代码如下所示:

private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
    Log("Exception: " + e.Exception.Message);
    e.Handled = true;
}
public static void Log(string message)
{
    File.AppendAllText(@"D:\Temp\log.txt", "[" + DateTime.Now.ToString("F") + "] [" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + "] " + message + Environment.NewLine);
}

此代码捕获了一些异常,但不是全部。 我发现WPF默认情况下会抑制数据绑定异常。 因为我的ViewModel是通过我的视图上的DataContext属性限制的,所以我认为这是问题所在。 我找到了这篇文章该文章定义了一个使用PresentationTraceSources类的TraceListener 现在可以捕获数据绑定异常,但是...不是通过MessageBus执行的代码中引发的异常。

我创建了一个演示此行为的解决方案,可以在此处下载。

这就是我遇到的问题。 我想念什么? 如何捕获这些异常?

预先感谢。

J.P

我认为这是在SimpleMVVM中实施MessageBus的错误或问题。

由于多个订阅者可以订阅一个令牌,因此当前实现确保即使一个注册的方法引发异常,每个订阅的方法也会被调用。 在这种情况下,将捕获异常并将其写出到控制台。

负责调用预订方法的方法是SafeNotify

private void SafeNotify(Action method, bool post) {
  try {
    // Fire the event on the UI thread
    if (post){
      if (Dispatcher.CheckAccess()){
        method();
      }
      else{
        Dispatcher.BeginInvoke(method);
      }
    }
    // Fire event on a ThreadPool thread
    else{
      ThreadPool.QueueUserWorkItem(o => method(), null);
    }
  }
  catch (Exception ex){
    // If there's an exception write it to the Output window
    Debug.WriteLine(ex.ToString());
  }
}

当方法调用在ThreadPool中排队时,您将没有机会处理引发的异常。 另请参阅此帖子以获取更多信息。

您唯一的选择是确保自己的注册方法的代码始终被try-catch-block包围。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM