2017-12-03 256 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属性。看到它如何获得价值并不容易。 –