2011-01-07 7 views
3

私は軽量のWPF MVVMフレームワークを開発しており、未処理の例外をキャッチして理想的にはそれらから回復できるようにしたいと考えています。私はApp.xaml.csのOnStartupメソッド内AppDomain.CurrentDomain.UnhandledExceptionのためのハンドラを登録した場合フレームワークレベルでWPFの例外をキャッチ

、:一瞬のためにこれをやっていないため、すべての良い引数を無視

は、私は次のような状況が発生しました次のように...

App.xaml.cs:予想通り

protected override void OnStartup(StartupEventArgs e) 
{ 
    AppDomain.CurrentDomain.UnhandledException += new 
    UnhandledExceptionEventHandler(this.AppDomainUnhandledExceptionHandler); 

    base.OnStartup(e); 
} 


void AppDomainUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs ea) 
{ 
    Exception e = (Exception)ea.ExceptionObject; 
    // log exception 
} 

、その後は私のVMのの1つに例外を発生させ、ハンドラが呼び出されます。

これまでのところ、このアプローチを使用して回復できる方法がないという点を除いて、私ができることは例外を記録し、CLRにアプリケーションを終了させることだけです。

私が実際にやりたかったのは、回復してメインのフレームワークVMに制御を戻すことでした。 (これをやることに対する動機を別にしておく)。

ので、いくつかの読書をして、私はコードは今、このようなものを見えるように問題がある

protected override void OnStartup(StartupEventArgs e) 
{ 
    AppDomain.CurrentDomain.UnhandledException += 
    new UnhandledExceptionEventHandler(this.AppDomainUnhandledExceptionHandler); 

    this.DispatcherUnhandledException += 
    new DispatcherUnhandledExceptionEventHandler(DispatcherUnhandledExceptionHandler); 

    base.OnStartup(e); 
} 

void AppDomainUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs ea) 
{ 
    Exception e = (Exception)ea.ExceptionObject; 
    // log exception 
} 

void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs args) 
{ 
    args.Handled = true; 
    // implement recovery 
} 

...、同じ場所にAppDomain.CurrentDomain.UnhandledExceptionのイベントハンドラを登録することを決定します一度私はthis.DispatcherUnhandledExceptionのハンドラを登録すると、イベントハンドラは呼び出されません。したがって、DispatcherUnhandledExceptionHandlerを登録すると、何らかの理由でAppDomain.CurrentDomain.UnhandledExceptionのハンドラーが非アクティブになります。

処理されていないVM例外を捕捉して回復する方法はありますか?

フレームワークにスレッドを明示的に使用することはありません。

答えて

5

理由は、あなたがこれを設定した(例外的にこれを明示的に行ったか、あるいはそうである可能性が高い、このように設定されたVSのデフォルト)ためです。 Debug->Exceptionsメニューを使用して、デバッグされたコードで例外が発生した場合のVisual Studioの動作を制御できます。

キャッチしても壊れることさえありますが、それは場合によっては非常に便利です。

マルチスレッドを使用していない場合は、メインUIスレッドで捕捉されないものすべてを捕捉するので、DispatcherUnhandledExceptionイベントで正常に処理する必要があります。

+0

ありがとうIsak、私が生成する可能性が高いすべての例外をキャッチすることを知っておくことが重要です。 –

2

自分の質問に素早く答え:

これは動作します...

App.xaml.cs:

protected override void OnStartup(StartupEventArgs e) 
{ 
    Application.Current.DispatcherUnhandledException += 
    new DispatcherUnhandledExceptionEventHandler(DispatcherUnhandledExceptionHandler); 

    base.OnStartup(e); 
} 

void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs args) 
{ 
    args.Handled = true; 
    // implement recovery 
    // execution will now continue... 
} 

[編集:私のコメントは以下の実装では何もありませんしかし、私の特定のIDE(Visual Studio)の設定は、IDEがキャッチしている例外に関してです。上記のIsakのコメントを参照してください。]

しかし、VisualStudioの中から実行している場合、VS例外通知ダイアログボックスが表示され、DispatcherUnhandledExceptionHandlerはF5キーを押しても続行されますが、その後、通常通りに実行が継続されます。

コンパイルされたバイナリをコマンドラインやWindowsエクスプローラから直接実行している場合は、仲介ポップアップなしで期待どおりにハンドラが呼び出されます。