一般情況下我們業務代碼不需要自己捕獲異常,因為目前我們常用框架都會自行處理異常,但是有些情況下需要自己處理異常,否則未處理的異常拋出會導致程序崩潰退出。
1.全局異常捕獲
// 1. AppDomain 未處理異常
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
var exception = e.ExceptionObject as Exception;
LogException(exception, "UnhandledException");
if (e.IsTerminating)
{
// 進程即將終止
EmergencyShutdown();
}
};
// 2. Task 未觀察異常 (.NET 4.0+)
TaskScheduler.UnobservedTaskException += (sender, e) =>
{
LogException(e.Exception, "UnobservedTaskException");
e.SetObserved(); // 防止進程崩潰
};
// 3. Windows Forms
if (Application.MessageLoop)
{
Application.ThreadException += (sender, e) =>
{
LogException(e.ception, "ThreadException");
};
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
}
// 4. WPF
Dispatcher.CurrentDispatcher.UnhandledException += (sender, e) =>
{
LogException(e.Exception, "DispatcherUnhandledException");
e.Handled = true; // 阻止進程崩潰
};
// 5. ASP.NET Core
// 在 Program.cs 中使用 UseExceptionHandler 中間件
2.Timer異常 和 異步void方法異常
定時器的事件方法中的代碼拋出來的異常,無法被全局異常捕獲,同樣異步void方法異常也是的,需要自行捕獲異常。
public class SafeTimer
{
private readonly Timer _timer;
public SafeTimer()
{
_timer = new Timer(OnTimerCallback);
}
private void OnTimerCallback(object state)
{
try
{
// 業務邏輯
}
catch (Exception ex)
{
// 記錄日誌,通知主線程
LogException(ex);
}
}
}
3.StackOverflowException和OutOfMemoryException
這兩個異常業務無法捕獲的,因為它們發生時,程序以及沒有辦法在執行如何代碼了,只能靠上個文章中説的崩潰自動收集dump,然後去分析dump找出問題。
還有其他比如調用c代碼等不安全代碼,大部分時候也時無法捕獲,如果它們引起異常也很難捕獲。
完