2017-12-03 258 views
1

我正在閱讀本書Under the hood of .NET memory management(由Red-Gate出版)。你可以找到一個pdf version on their website本書中的事件處理程序「.NET內存管理的底層」

我以爲我理解事件處理程序與發佈者和訂閱者之間創建的引用有關,但作者對第5章「特定於應用程序的問題」中的事件處理程序的解釋(標題爲「Windows Presentation Foundation」)迷惑了我。

在第160-161頁上,他們描述了一個使用主/從關係的UI設計。我引用(方括號中的數字是我的,爲了創建我的問題的參考,雙關語與其說意):

您可能必須與主記錄列表 一個網格,當你點擊來自主網格的記錄,將打開一個新窗口 ,其中包含與該主記錄相關的詳細信息。如果主窗口在詳細信息窗口[1]中連接了 事件,則無法收集詳細信息窗口,直到主窗口中的 事件處理程序釋放其對詳細信息窗口的引用[2]。在這個 的情況下,細節窗口將是監聽器,主窗口是源文件[3]。在大多數 的情況下,主窗口將超出詳細信息窗口,但如果事件處理程序 處理不當,則只要 主窗口處於活動狀態,就無法收集詳細信息窗口。

Detail.SomeEvent += new EventHandler(Master.SomeEvent_Handler); [4] 

[1]這是術語非常不清楚。誰「連線」誰?僅憑這一點,我就無法確定誰是聽衆,誰是訂閱者(我只能假設......)。下一句[3]似乎回答了這個問題,說主人是信息來源,細節是聽衆,但是隻有在引入了混淆之後,在[2]中說明完全相反(因爲事件處理程序是主窗口中的而不是)。

代碼示例[4]也不符合[3]中的內容(但對應於[2])。如果主窗口是源,那麼它應該是:

Master.SomeEvent += new EventHandler(Detail.SomeEvent_Handler); [5] 

對不對?

除了所有這些混亂,我理解事件處理程序如下。如果Master有事件,Detail訂閱(如[5]),那麼MasterDetail有抵觸(因爲對實例刪除的引用創建對實例的引用,在這種情況下爲Detail)。因此,只要Master生活,Detail也將被保存在內存中,除非事件處理程序與事件分離。

我對這本書的批評和我自己的理解是否正確?

回答

1

它從來沒有從C#語法糖非常明顯。委託構造函數需要引用兩個參數。顯而易見的是事件處理程序方法。非顯而易見的一個是其處理程序方法將被調用的對象。非顯而易見,因爲您從不在代碼中輸入它。它是this。 C#甚至不允許你指定它,其他語言也可以。

所以Master對象現在如何對Detail對象進行引用,這是正確調用事件處理函數方法所必需的。

因此,只要Master對象處於活動狀態,Detail對象不會被收集。除非您明確退訂該事件或使用WPF弱事件模式。或者,理想情況下,設計代碼以使Master和Detail對象同時死亡。他們給了你一個不容易做的例子。

還有其他方法可以做到不使用事件。您可以使用代表您要提出的事件的方法來聲明IDetail接口。給Master類一個AddDetail(IDetail)和RemoveDetail(IDetail)方法。現在內存管理非常清晰,當您忘記調用RemoveDetail()時,它變得更加明顯。然而,WPF設計人員非常青睞使用事件,他們必須提出弱事件模式以避免他們自己的對象模型中的泄漏。

+0

非顯而易見的'this'參數有什麼意義?它是否設置上下文(如在JavaScript?(赦免異端))?你能指點我一些文件或書嗎?我想了解更多。 – bvgheluwe

+0

沒什麼特別深的。該事件正在調用一個實例方法,它需要一個對象引用。代表存儲它。請注意Delegate.Target屬性。看到它如何獲得價值並不容易。 –