2025年4月15日 星期二

[研究]ASP.NET, using配置記憶體在 using 結束後是否立刻釋放?

[研究]ASP.NET, using配置記憶體在 using 結束後是否立刻釋放?

2025-04-15

為了改善 System.OutOfMemoryException 問題,研究一下。

**********

ASP.NET, WebForm, 請問 using ( ) { ... } 方式配置的記憶體,using 結束後會立刻釋放 ? 還是等待 .NET Framework 的記憶體回收機制 可能過一段時間才回收 ? 

ChatGPT 說:

在 ASP.NET WebForms 或一般 .NET Framework 程式中,using (...) { ... } 區塊的主要用途是用來自動釋放實作了 IDisposable 介面的物件資源。這個釋放動作發生在 using 區塊結束的當下立刻執行,但這和記憶體回收(Garbage Collection,GC)是兩回事。

using 區塊做了什麼?

using (var stream = new FileStream("path.txt", FileMode.Open))
{
    // 使用 stream
} // 這裡會自動呼叫 stream.Dispose()

  • using 結束後,會馬上呼叫 Dispose() 方法。
  • Dispose() 是用來釋放「非受控資源(unmanaged resources)」,例如檔案控制代碼、資料庫連線、網路連線等。
  • 如果物件內部使用到大量非受控資源(像是 SqlConnection, FileStream, Bitmap, StreamReader, HttpClient 等),這時候釋放就非常關鍵。

🧠 那「記憶體」什麼時候釋放?

  • using 結束時,只保證 呼叫 Dispose()。
  • 記憶體本體的釋放,還是由 .NET 的垃圾回收機制(GC) 決定的。
  • 也就是說,那個物件的記憶體可能會在 Dispose() 後的一段時間才被 GC 自動釋放,除非你主動呼叫:

GC.Collect(); // 不建議常用,除非特殊需求   


🔍 結論

行為時機
呼叫 Dispose()馬上在 using 區塊結束時執行
記憶體釋放(GC)由 GC 自動判斷時間,不一定馬上

如你是開發 WebForm 應用,特別要注意的場景包括:

  • SqlConnection, SqlCommand, DataReader、或其他資源密集型物件一定要用 using 包起來,避免資源未釋放導致效能下降或資源鎖死。

相關參考資料

using 陳述式 - 確保正確使用可處置的物件
https://learn.microsoft.com/zh-tw/dotnet/csharp/language-reference/statements/using
using 結束會自動呼叫 Dispose()

IDisposable 介面
https://learn.microsoft.com/zh-tw/dotnet/api/system.idisposable?view=net-9.0
Dispose() 是釋放「非受控資源」

記憶體回收
https://learn.microsoft.com/zh-tw/dotnet/standard/garbage-collection/
using 不會釋放記憶體(GC 是分開的)

GC.Collect 方法
https://learn.microsoft.com/zh-tw/dotnet/api/system.gc.collect?view=net-9.0
GC.Collect() 是不建議頻繁主動呼叫的

(完)



沒有留言:

張貼留言