2

我正在追踪某些应用程序中的内存泄漏。许多表单共享相同的 Spellchecker 对象,因此比任何单独的表单都要好。我知道,如果未正确删除处理程序事件,这可能会导致内存泄漏。

AddHandler 和 RemoveHandler 对我来说很有意义,因为很明显如果调用了 AddHandler,那么应该有一个相应的 RemoveHandler。但是,Handles 关键字会自动为您删除处理程序吗?

Private Sub spellingContextMenu_Popup(ByVal sender As Object, ByVal e As System.EventArgs) Handles spellingContextMenu.Popup

在上面,如果 spellingContextMenu 存在很长时间但表单死了,那么应该手动删除处理程序吗?

Microsoft 自己的页面没有提供关于此http://msdn.microsoft.com/en-us/library/6k46st1y.aspx#feedback的指导

4

1 回答 1

5

Handles关键字基于正常事件订阅实践可以工作的假设,垃圾收集器负责收集事件源、事件订阅者和委托对象。当事件源没有超过订阅者时,它可以正常工作。一个很好的例子是窗体内的控件,当窗体关闭时,其中的所有控件也会死掉。因此,下一次垃圾收集会清除所有这些,包括由Handles创建的任何委托对象。无需明确取消订阅。

如果您的 ContextMenu 超出使用它的表单,这听起来不像您的情况。而且您确实有 GC 问题,您的 ContextMenu 通过其事件处理程序在表单上保留一个引用,因此在收集菜单之前不会收集它。所以使用Handles不是正确的解决方案,你确实需要显式调用 AddHandler 和 RemoveHandler。

一定要密切注意球,不只是为每个表单创建一个新的 ContextMenu 真的有什么意义吗?这可以轻松解决您的问题。另一种方法是不使用事件,而是让表单实现接口。您使用拼写检查器类注册表单对象,它可以侦听 Disposed 事件以知道它应该删除引用并停止通过接口进行回调。

并且要注意 VB.NET 中的一个错误,如果您构建程序集的调试版本,那么如果您在没有附加调试器的情况下运行它,它将为每个声明为 WithEvents 的事件泄漏一个 WeakReference。它是为实现编辑 + 继续支持而创建的,您必须部署程序集的发布版本以避免这种泄漏。

于 2013-09-03T12:35:48.873 回答