2011-01-07 85 views
3

我正在開發一個輕量級WPF MVVM框架,並希望能夠捕獲未處理的異常,並從中理想地恢復。在框架級別捕獲WPF異常

暫時忽略所有的很好的理由不這樣做,我會遇到以下情況:

如果我的App.xaml.cs的OnStartup方法內註冊AppDomain.CurrentDomain.UnhandledException處理程序,如下...

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 
} 

,然後我的虛擬機的一個內引發異常,如預期的處理程序被調用。

到目前爲止,除了使用這種方法無法恢復的事實之外,我所能做的就是記錄異常,然後讓CLR終止應用程序。

我真正想要做的是恢復,並返回到主框架虛擬機的控制。 (再次摒棄這樣做的動機)。

所以,做一些閱讀,我決定在同一個地方登記爲AppDomain.CurrentDomain.UnhandledException的事件處理程序,這樣的代碼現在看起來是這樣的......

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 
} 

的問題是一旦我爲this.DispatcherUnhandledException註冊處理程序,無論是否調用了事件處理程序。因此,註冊DispatcherUnhandledExceptionHandler以某種方式停用AppDomain.CurrentDomain.UnhandledException的處理程序。

有沒有人有辦法從未處理的VM異常中捕獲和恢復?

提到在框架中沒有明確使用線程可能很重要。

回答

5

VS向你展示異常的原因是因爲你已經將它設置爲這樣(要麼你明確地這樣做了 - 或者更有可能 - VS中的默認配置就像這樣)。您可以通過Debug->Exceptions菜單控制Visual Studio在調試代碼中遇到異常時的操作。

即使您有一個在某些情況下非常方便的捕捉,您甚至可以讓它突破。

如果你不使用多線程,那麼你應該罰款DispatcherUnhandledException事件,因爲它會捕獲在主UI線程上捕獲的所有東西。

+0

謝謝Isak,知道我會捕獲所有可能產生的異常是很重要的。 – 2011-01-07 19:11:44

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/continue時被調用,之後執行將按照正常進行。

如果您直接運行編譯後的二進制文件,即從命令行或通過Windows資源管理器運行,那麼該處理程序將按照您的預期調用,而無需任何中間彈出窗口。