簡體   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