2

SimpleMVVM フレームワークを使用して WPF アプリケーションを構築していますが、例外をキャッチできません。SimpleMVVM の MessageBus を使用して、別のビューモデルにメッセージを送信します。これはすべて正常に動作しますが、メッセージバスによって実行されるコードで発生した例外が抑制されることに気付きました。ここに私がこれまでに持っているものがあります:

Myには、MainWindowViewModelMainWindowで起動するボタンが含まれていますTempCommand。このコマンドはTest、SimpleMVVM の MessageBus を使用して通知メッセージを送信するメソッド (以下に示す) を呼び出します。

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

MyMainWindowにもFramewith コンテンツが含まれています。このコンテンツの 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アプリケーションをデバッグすると、メソッドが呼び出され、例外が発生していることがはっきりとわかります。でもなぜかそれだけ。アプリケーションは影響を受けず、例外トラップ コードは例外を認識しません。

2 つの方法で例外をトラップします。1 つ目は、次のイベントを処理すること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 はデフォルトでデータバインディングの例外を抑制することがわかりました。ViewModels はDataContextビューのプロパティを介してバインドされているため、これが問題だと思いました。クラスを使用するを定義するこの記事を見つけました。データバインディングの例外がキャッチされるようになりましたが、MessageBus を介して実行されるコードでスローされた例外ではありません。TraceListenerPresentationTraceSources

この動作を示すソリューションを作成しました。ここからダウンロードできます。

そして、これは私が立ち往生しているところです。私は何が欠けていますか?これらの例外をキャッチするにはどうすればよいですか?

よろしくお願いします。

JP

4

1 に答える 1

1

SimpleMVVMでのMessageBusの実装のバグまたは問題だと思います。

複数のサブスクライバーがトークンをサブスクライブできるため、現在の実装では、1 つの登録済みメソッドが例外をスローした場合でも、サブスクライブされた各メソッドが確実に呼び出されるようになっています。この場合、例外がキャッチされ、コンソールに書き出されます。

サブスクライブされたメソッドの呼び出しを担当するメソッドは 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 で囲まれていることを確認することです。

于 2013-02-12T13:27:41.650 に答える