[英]Garbage Collection misunderstanding in c#
我搜索谷歌沒有得到我想要的東西。 我不知道我是對還是錯。 看,我試圖了解GC.Collect()所以這里是代碼..
public class SomePublisher
{
public event EventHandler SomeEvent;
}
public class SomeSubscriber
{
public static int Count;
public SomeSubscriber(SomePublisher publisher)
{
publisher.SomeEvent += new EventHandler(publisher_SomeEvent);
}
~SomeSubscriber()
{
SomeSubscriber.Count++;
}
private void publisher_SomeEvent(object sender, EventArgs e)
{
// TODO: something
}
}
我在我的主線程中這樣做..
SomePublisher publisher = new SomePublisher();
for (int i = 0; i < 10; i++)
{
SomeSubscriber subscriber = new SomeSubscriber(publisher);
subscriber = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(SomeSubscriber.Count.ToString());
Console.ReadLine();
我得到輸出0,但根據我應該是10,因為GC.Collect()必須從內存中刪除class1對象,所以必須調用class1析構函數,所以計數必須增加到10 ..可以任何正文解釋這個..
(另請注意,C#沒有析構函數1 ,它有終結器。這些是非常不同的東西,你不應該混淆它們。)
“問題”就在這條線上:
publisher.SomeEvent += new EventHandler(publisher_SomeEvent);
這將創建一個以特定對象實例的publisher_SomeEvent()
方法為目標的委托,並將此委托添加到publisher.SomeEvent
事件的調用列表中。 此委托對象引用目標對象,並阻止對象的收集! (這是一件好事 - 如果您將委托委托給特定對象上的方法,那么在不再引用委托之前,您不希望收集該對象。)
這在技術上根本不是問題,而是運行時保持對象仍然存在仍然被引用。
為了說明,這是參考鏈:
SomePublisher -+-> EventHandler --> SomeSubscriber
|
+-> EventHandler --> SomeSubscriber
|
+-> (Eight more...)
在調用GC.Collect()
之前,您需要執行以下兩項操作之一:
SomePublisher
對象之前取消訂閱該事件。 這將使EventHandler
委托實例和它們引用的SomeSubscriber
實例都有資格進行收集。 publisher = null;
。 這將導致整個對象圖符合收集條件。 在這兩種情況下,這將釋放對SomeSubscriber
對象的所有引用。
1請注意,C#規范確實將這些代碼塊稱為“析構函數”,但這是一個可怕的名稱。 那些熟悉垃圾收集語言的人會對它感到困惑,因為“終結器”是垃圾收集器在不再可以訪問對象時調用的代碼的廣泛術語。 特別是C ++開發人員會期望析構函數在不同的時間執行。 所以是的,C#有一個叫做“析構函數”的東西,但它不是一個析構函數。 (說些什么不是這樣!)
SomeSubcriber對象的終結器直到最后才會被調用。 因為即使SomeSubscriber對象設置為null,它的內存仍然被SomePublisher對象的事件SomeEvent引用,該對象在應用程序結束之前一直存在。 因此,當調用GC.Collect()時,垃圾收集器將找不到要放入終結器隊列的任何對象。
public SomeSubscriber(SomePublisher publisher)
{
// publisher.SomeEvent += new EventHandler(publisher_SomeEvent);
}
如果我們可以通過上面的代碼替換SomeSubcriber的構造函數,那么我們將在控制台中將結果作為10。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.