书中的事件处理程序"在.NET内存管理的引擎下"

时间:2017-12-03 09:56:11

标签: .net memory-management event-handling

我正在阅读这本书Under the hood of .NET memory management(由Red-Gate出版)。您可以找到pdf version on their website

我认为我理解了在发布者和订阅者之间创建的引用的事件处理程序,但作者'第5章和第34章中对事件处理程序的解释;特定于应用程序的问题" (标题为#34; Windows Presentation Foundation")让我困惑。

在第160-161页,他们描述了使用主/明细关系的UI设计。我引用(方括号之间的数字是我的,以便为我的问题创建引用,而不是那么多的意思):

  

您可能有一个包含列表的网格   主记录,当您从主网格中单击记录时,会出现一个新窗口   打开,显示与该主记录关联的详细信息。如果主窗口接通电源   在详细信息窗口[1]中的事件,然后细节窗口不能被垃圾收集,直到   主窗口中的事件处理程序释放它们对详细信息窗口的引用[2]。在这   例如,详细信息窗口将是监听器,主窗口是源[3]。多数情况   例如,主窗口将比详细信息窗口更长,但是如果事件处理程序是   处理不当,那么细节窗口就不能被垃圾收集了   主窗口还活着。

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

[1]这是非常不明确的术语。谁"连线"谁?仅凭这一点,我无法确定谁是听众以及谁是订阅者(我只能假设......)。下一句[3]似乎通过说主人是源而细节是听众来解答这个问题,但只是在通过在[2]中说明完全相反的情况引入混淆之后(因为imo事件处理程序在主窗口中

代码示例[4]也与[3]中所述内容相对应(但与[2]相对应)。如果主窗口是源,那么它应该是:

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

右?

除了所有这些混乱之外,我理解事件处理程序如下。如果Master包含Detail订阅的事件(如[5]所示),那么Master会对Detail产生一种拒绝(因为对实例删除的引用会创建一个引用实例,在这种情况下为Detail。因此,只要Master存在,Detail也将保留在内存中,除非事件处理程序与事件分离。

我对这本书的批评和我自己的理解是否正确?

1 个答案:

答案 0 :(得分:1)

C#语法糖从来都不是很明显。委托构造函数引用了两个参数。显而易见的是事件处理程序方法。非显而易见的是将要调用其处理程序方法的对象。不明显因为你从不在代码中输入它。它是this。 C#甚至不允许您指定它,其他语言也可以。

所以Master对象现在如何引用Detail对象,正确调用事件处理程序方法。

因此只要Master对象处于活动状态,就不会收集Detail对象。除非您再次明确取消订阅该事件或使用WPF弱事件模式。或者,理想情况下,设计代码以使Master和Detail对象同时死亡。他们给了你一个不容易做的例子。

还有其他方法可以不使用事件。您可以使用表示您要引发的事件的方法声明IDetail接口。并为Master类提供AddDetail(IDetail)和RemoveDetail(IDetail)方法。现在,内存管理非常清晰,当您忘记调用RemoveDetail()时,内存管理变得更加明显。然而,WPF设计者非常喜欢使用事件,他们必须提出弱事件模式以避免他们自己的对象模型中的泄漏。