[英]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.