亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

C# 中的“處置模式”:為什么我們需要“if(處置)”條件?

C# 中的“處置模式”:為什么我們需要“if(處置)”條件?

C#
慕妹3146593 2022-12-04 13:04:03
因此,默認的處置模式實現如下所示:class SomeClass : IDisposable{   // Flag: Has Dispose already been called?   bool disposed = false;   // Public implementation of Dispose pattern callable by consumers.   public void Dispose()   {       Dispose(true);      GC.SuppressFinalize(this);              }   // Protected implementation of Dispose pattern.   protected virtual void Dispose(bool disposing)   {      if (disposed)         return;       if (disposing) {         // Free any other managed objects here.      }      // Free any unmanaged objects here.      disposed = true;   }   ~SomeClass()   {      Dispose(false);   }}據說:如果方法調用來自終結器(即,如果處置是 false),則僅執行釋放非托管資源的代碼。由于未定義垃圾收集器在終結期間銷毀托管對象的順序,因此Dispose使用值調用此重載false可防止終結器嘗試釋放可能已被回收的托管資源。問題是:為什么假設被 object of 引用的對象SomeClass可能已經被釋放,我們不應該在從 finalizer 調用方法時嘗試釋放它們?如果那些對象仍然被我們的SomeClass對象引用,它們就不能被釋放,不是嗎?據說:那些有掛起(未運行)終結器的(暫時)保持活動狀態,并被放入一個特殊的隊列中。[...] 在每個對象的終結器運行之前,它仍然非?;钴S——該隊列充當根 對象。因此,我們的SomeClass對象再次被該隊列引用(這與被根引用相同)。對象引用的其他對象SomeClass也應該是活動的(因為它們是通過SomeClass對象生根的)。那么為什么以及如何在SomeClass調用終結器時釋放它們呢?
查看完整描述

2 回答

?
慕斯王

TA貢獻1864條經驗 獲得超2個贊

Konrad Kokosa 在他的《Pro .NET Memory Management 》一書中有一個令人印象深刻的解釋。(強調)

在 GC 期間,在標記階段結束時,GC 檢查終結隊列以查看是否有任何可終結對象已死亡。如果它們是一些,它們還不能被刪除,因為它們的終結器需要被執行。因此,這樣的對象被移動到另一個名為 fReachable queue 的隊列。它的名字來自于它代表最終化可達對象的事實——那些現在只因為最終化才可達的對象。如果找到任何此類對象,GC 會向專用終結器線程指示有工作要做。

終結線程是由 .NET 運行時創建的另一個線程。它從 fReachable 隊列中一個一個地移除對象并調用它們的終結器。這發生在 GC 恢復托管線程之后,因為終結器代碼可能需要分配對象。由于此對象的唯一根已從 fReachable 隊列中刪除,下一次譴責此對象所在世代的 GC 將發現它不可訪問并回收它。

此外,fReachable 隊列在 Mark 階段被視為根,因為終結器線程可能不夠快,無法在 GC 之間處理來自它的所有對象。這使可終結對象更多地暴露于中年危機——它們可能會停留在 fReachable 隊列中一段時間,僅僅因為等待終結而消耗第 2 代。

我認為這里的關鍵是:

fReachable 隊列在 Mark 階段被視為根,因為終結器線程可能不夠快,無法在 GC 之間處理來自它的所有對象。


查看完整回答
反對 回復 2022-12-04
?
慕的地10843

TA貢獻1785條經驗 獲得超8個贊

.NET 中的對象在存在對它們的任何引用時就存在。一旦最后一個引用不存在,它們就會不復存在。當對象存在時,對象使用的存儲將永遠不會被回收,但是 GC 在回收存儲之前會做幾件事:

  1. 有一個特殊的列表,稱為“終結器隊列”,它包含對所有已注冊終結器的對象的引用。在識別出 Universe 中任何地方存在的所有其他引用之后,GC 將檢查終結器隊列中的所有對象,以查看是否找到了對它們的任何引用。如果此過程導致它找到以前未發現的對象,它會將引用復制到另一個稱為“freachable 隊列”的列表。任何時候 freachable 隊列非空并且沒有終結器正在運行,系統將從該隊列中提取一個引用并調用終結器。

  2. GC 還將檢查所有弱引用的目標,并使目標未被任何有效強引用識別的任何弱引用無效。

請注意,finalize 方法不會“垃圾收集”對象。相反,它會延長對象的存在直到finalize被調用,目的是允許它履行對外部實體可能具有的任何義務。如果那時在宇宙中任何地方都不存在對該對象的引用,則該對象將不復存在。

請注意,兩個具有終結器的對象可能會相互引用。在這種情況下,它們的終結器運行的順序是未指定的。


查看完整回答
反對 回復 2022-12-04
  • 2 回答
  • 0 關注
  • 127 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號