什麼是終結器隊列和 Control+ThreadMethodEntry?
我有一個似乎洩漏記憶體的 WindowsForms 應用程序,因此我使用 Redgate 的 ANTS Memory Profiler 來查看我懷疑的對象,發現它們僅由已在Finalizer Queue上的對象持有。太好了,究竟什麼是終結器隊列?你能指出我最好的定義嗎?你能分享一些軼事建議嗎?
此外,Finalizer Queue 上的所有根 GC 對像都是名為“caller”的**System.Windows.Forms.Control+ThreadMethodEntry對象的實例。**我看到它涉及多執行緒UI互動,但除此之外我知道的不多。原諒我明顯的懶惰和承認的無知,但這些資源都埋在供應商的組件中。我正在與供應商討論這些問題,但我需要一些指導來加快對話速度。你能指出我對 ThreadMethodEntry 最有用的定義嗎?有什麼軼事建議嗎?
另外,我什至應該關注終結器隊列中的這些對象嗎?
**更新:**這篇紅門文章很有幫助。
終結器隊列包含所有定義了終結器方法的對象。回想一下,終結器是一種收集非託管資源(如句柄)的方法。當垃圾收集器收集垃圾時,它會將任何帶有終結器的對象移動到終結器隊列中。在稍後的某個時刻——取決於記憶體壓力、GC 啟發式和月相——當垃圾收集器決定收集這些對象時,它會沿著隊列向下走並執行終結器。
過去曾處理過記憶體洩漏,在終結器隊列中看到一堆供應商的對象可能是草率的程式碼,但這並不表示記憶體洩漏。通常,好的程式碼會公開一個 Dispose 方法,該方法將收集託管和非託管資源,並在這樣做時通過
GC.SuppressFinalize(). 因此,如果供應商的對象確實實現了 Dispose 方法,而您的程式碼沒有呼叫它,則可能會導致終結器隊列中出現一堆對象。您是否嘗試過在 ANTS 中創建兩個時間點之間的快照並比較它們之間創建的對象?這可以幫助您辨識任何被洩露的託管對象。
此外,如果您想查看執行終結器時記憶體是否消失,請嘗試以下方法進行測試:
System.GC.Collect(); System.GC.WaitForPendingFinalizers(); // 此方法在執行終結器時可能會阻塞 System.GC.Collect();我不建議正常執行此程式碼。如果您剛剛完成了大量工作並產生了大量垃圾,您可能想要執行它。例如,在我們的應用程序中,我們的一個函式可以創建大約 350 MB 的垃圾,這些垃圾在關閉 MDI 視窗後會被浪費掉。由於已知這會留下大量垃圾,因此我們手動強制進行垃圾收集。
另請注意,基本 Windows.Forms 程式碼中有一個低級屬性記憶體,它將保留最後打開的模式對話框。這可能是記憶體洩漏的來源。擺脫這個引用的一個可靠方法是強制出現另一個簡單的對話框,然後執行上面的 GC 程式碼。