[研究]ASP.NET, 攔截 System.OutOfMemoryException
2025-04-14
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
********************************************************************************
ASP.NET , Webform, try catch 如何攔截 'System.OutOfMemoryException' 問題 ?
ChatGPT 說:
在 ASP.NET Web Forms 中,System.OutOfMemoryException 是一種 critical error(重大例外),通常表示應用程式的記憶體資源已經用盡,無法再分配更多記憶體。雖然你可以使用 try-catch 嘗試攔截它,但在實務上 這類錯誤常常會導致應用程式崩潰或不穩定,即使有 try-catch 包住也未必有效防範或繼續執行程式。
.aspx.cs 中用 try-catch 包起來的基本範例
try { // 模擬可能導致記憶體爆炸的操作 byte[] hugeArray = new byte[int.MaxValue]; // 這幾乎會直接爆掉 // 其他邏輯 } catch (OutOfMemoryException ex) { // Logging:記錄錯誤 LogError("Out of memory: " + ex.Message); // 顯示友善錯誤頁 Server.Transfer("OutOfMemoryErrorPage.aspx"); } catch (Exception ex) { // 一般例外處理 LogError("General error: " + ex.Message); } |
為什麼攔不住?
- OutOfMemoryException 發生時,系統可能已經無法提供足夠的資源來正常執行 catch 區塊內的程式碼(例如 logging、轉頁等)。
- 某些情況下 ASP.NET 執行緒甚至會被終止。
****************************************
更推薦的方式:在 Global.asax的 Application_Error中處理
.aspx.cs 中不用 try-catch 包起來
byte[] hugeArray = new byte[int.MaxValue]; // 這幾乎會直接爆掉 |
在 Global.asax的 Application_Error中處理
protected void Application_Error(object sender, EventArgs e) { Exception ex = Server.GetLastError(); if (ex is OutOfMemoryException) { // 記錄錯誤 LogError("應用程式記憶體耗盡: " + ex.Message); // 清除錯誤並導向錯誤頁 Server.ClearError(); Response.Redirect("~/OutOfMemoryErrorPage.aspx"); } } |
註:實際測試,如果 Default.aspx.cs 中已經有 try ... catch 攔截,Global.asax 中的 Application_Error 中就攔截不到了。
註:實際測試,如果 Default.aspx.cs 中沒有 try ... catch 攔截,Global.asax 中的 Application_Error 中依然攔截不到,下圖。
****************************************
其他預防建議:
- 避免大資料操作(如載入大型檔案到記憶體、產生大型報表等)。
- 釋放不用的資源
using (MemoryStream ms = new MemoryStream()) { // 使用完畢會自動釋放記憶體 } |
- 使用 64-bit 應用程式池,讓 ASP.NET 可使用更多記憶體(預設 IIS 常是 32-bit)。
- 使用 GC.Collect() 非常謹慎! 通常不建議手動叫用垃圾回收,除非你確定真的需要。
(完)
相關
沒有留言:
張貼留言