首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Windows Forms 未處理例外完整處理指南:UI 執行緒與非 UI 執行緒雙重防護

     編輯:關於.NET

問題背景

WinForms 應用程式若發生未捕獲的例外,預設會彈出系統錯誤對話框並終止程式,嚴重影響使用者體驗。本文示範如何透過 Application.ThreadException 與 AppDomain.UnhandledException 兩大事件,實現全域例外攔截、友善提示與日誌記錄。

預設行為展示

按鈕點擊直接拋出例外:

private void button1_Click(object sender, EventArgs e)
{
    throw new Exception();
}

執行結果將顯示預設的 CLR 未處理例外對話框:

預設未處理例外對話框

解決方案:雙事件攔截

  • Application.ThreadException:處理 UI 執行緒 (主執行緒) 上的未捕獲例外。
  • AppDomain.CurrentDomain.UnhandledException:處理非 UI 執行緒 (背景執行緒、ThreadPool 等) 的未捕獲例外。

完整 Program.cs 實作

static class Program
{
    [STAThread]
    static void Main()
    {
        // 1. 註冊 UI 執行緒例外處理
        Application.ThreadException += Application_ThreadException;
        // 2. 註冊非 UI 執行緒例外處理
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        HandleException(e.ExceptionObject as Exception, "非 UI 執行緒");
    }

    static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
    {
        HandleException(e.Exception, "UI 執行緒");
    }

    static void HandleException(Exception ex, string threadType)
    {
        if (ex == null) return;
        MessageBox.Show($"抱歉,操作失敗 ({threadType})。請重試或聯繫技術支援。\n詳細錯誤:{ex.Message}",
                        "系統錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
        LogException(ex);
    }

    static void LogException(Exception ex)
    {
        // 實際專案請接入 Log4Net、Serilog 或寫入事件檢視器
        System.Diagnostics.Debug.WriteLine($"[{DateTime.Now}] {ex}");
    }
}

執行效果

套用上述程式碼後,同樣的按鈕點擊將彈出自訂的友善錯誤視窗,程式不會強制終止:

自訂錯誤提示視窗

進階建議

  1. 區分嚴重等級:依例外類型決定是否允許程式繼續執行 (如 ThreadAbortException 應重新拋出)。
  2. 記錄完整堆疊:日誌務必包含 ex.ToString() 以取得完整堆疊追蹤。
  3. 搭配 Application.SetUnhandledExceptionMode:可強制所有 UI 執行緒例外走 ThreadException 事件,避免某些情況下仍彈出系統對話框。

總結

透過雙事件機制,WinForms 即可實現健全的全域例外處理,大幅提升應用程式穩定度與使用者體驗。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved