WPF 程序 處理未捕獲異常,和程序莫名終止說拜拜


百密一疏的Bug很難避免,沒有誰能保證,我的程序永遠 0 BUG;

 

突然接手一個很龐大的項目,在項目運行期間會莫名異常結束,異常極難重現,還找不出BUG代碼,代碼太多了。

這個時候就需要把程序中發生的BUG記錄下來,知道哪里BUG了,才好下次更新解決。

把所有代碼全部加 try catch ?  那就懷孕了,真的搞大了。

 

未捕獲的異常處理:

一:C# 在 Application 類中提供了 DispatcherUnhandledException 事件,用於處理UI線程上未捕獲的異常

App.Current.DispatcherUnhandledException += App_DispatcherUnhandledException;
void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
//e.Exception 發生的異常
//e.Handled 是否已處理異常事件
}

但是 DispatcherUnhandledException 捕獲不了 非UI線程上發生的異常

 

二:C# 在 AppDomain 類中提供了 UnhandledException 事件,用於捕獲應用程序域中發生的異常

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    MessageBox.Show("Unhandle");
//MessageBox.Show((e.ExceptionObject == null ? "Null" : e.ExceptionObject.GetType().Name),
    //    "CurrentDomain_UnhandledException:");
}

這樣就能捕獲應用程序域中發生的異常,當然,包括UI線程和非UI線程異常,如果你有創建應用程序域的需求,創建完成,再綁定下事件即可。

但是AppDomain.UnhandledException 事件沒有提供 終止異常,也就是說,異常發生了,你沒捕獲,這里通知一下,但是該程序結束還得結束。

 

在這里要特別提到官方封裝的 Delegate.BeginInvoke();

"已知:"在異步函數中發生了異常並且沒處理:

"求解:"

1.沒調用 Delegate.EndInvoke() 函數:

    終止執行。 程序不會掛掉,異常丟棄。這是種很隱蔽的BUG,很難發現。

    AppDomain.UnhandledException 事件不會通知發生了異常,這里要特別注意。

public void Hello()
{
    World();
    Load();
}

public void World()
{
throw new Exception();
}
public void Load() { MessageBox.Show("Suc"); } var action = new Action(Hello); action.BeginInvoke(null, null);

像這種示例,如果在World() 方法中發生了異常,線程會立即終止,Load() 函數就不會執行,程序也不會終止。

一個函數沒有執行,也許就會導致很嚴重的異常,還很難發現。

 

2.調用了 Delegate.EndInvoke() 函數:

    異常拋出, 程序掛掉。

    AppDomain.UnhandledException 事件會通知發生了異常

 

這里也許會有個需求,如果我想處理 AppDomain.UnhandledException 事件中的異常怎么辦?程序掛了太惡心了。

我們來繼續擴展這個框架

解決在非UI線程中訪問UI 異常的小方法

/// <summary>
/// 委托 擴展類
/// </summary>
public static class DelegateExtension
{
/// <summary> /// 可以被捕獲異常的異步調用 /// </summary> /// <param name="dele"></param> public static void UnsafeBeginInvoke(this Delegate dele) { var action = new Action(() => { dele.DynamicInvoke(); }); action.BeginInvoke(new AsyncCallback((ar) => { try { action.EndInvoke(ar); } catch (Exception ex) { App.Current.Dispatcher.BeginInvoke(new Action(() => { throw ex; })); } }), null); } }

有點不倫不類哈,厄。把異常推送到UI線程上拋出,讓Application.DispatcherUnhandledException 事件處理

 

其它:C# 在 TaskScheduler 類中提供了 UnobservedTaskException 事件,用於捕獲 Task 異步異常.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM