.net - VB.Net Handles 关键字 - 我需要手动调用RemoveHandler吗?

标签 .net vb.net

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

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

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

在上面,如果拼写上下文菜单存在很长时间但表单死亡,那么是否应该手动删除处理程序?

微软自己的页面没有提供这方面的指导http://msdn.microsoft.com/en-us/library/6k46st1y.aspx#feedback

最佳答案

Handles 关键字基于这样的假设:正常的事件订阅实践可以工作,垃圾收集器负责收集事件源、事件订阅者和委托(delegate)对象。当事件源的生命周期不超过订阅者时,这种方法可以正常工作。一个很好的例子是窗体内的控件,当窗体关闭时,窗体内的所有控件也会消失。因此,下一次垃圾收集将清除所有这些对象,包括由 Handles 创建的任何委托(delegate)对象。无需明确取消订阅。

如果您的 ContextMenu 比使用它的表单生命周期更长,这听起来不像您的情况。而且您确实遇到了 GC 问题,您的 ContextMenu 通过其事件处理程序保留对表单的引用,因此在收集菜单之前不会收集它。因此,使用 Handles 并不是正确的解决方案,您确实需要显式调用 AddHandler 和 RemoveHandler。

请密切关注,不只是为每个表单创建一个新的 ContextMenu 真的有任何意义吗?这很简单地解决了你的问题。另一种方法是不使用事件,但让表单实现接口(interface)。您使用拼写检查器类注册表单对象,它可以监听 Dispose 事件以知道它应该删除引用并停止通过接口(interface)进行回调。

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

关于.net - VB.Net Handles 关键字 - 我需要手动调用RemoveHandler吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18590769/

相关文章:

c# - 如何使用 CultureInfo 获取 12 小时或 24 小时时间(不带日期)

c# - 将一个 Excel 文件中的不同工作表导出到不同的 pdf 文件中?

VB.NET 使用 LINQ to XML 向 XML 文档添加元素

vb.net - 如何在枚举中包含整数字符串?

vb.net - 自定义控件中的文本属性丢失值

mysql - 使用带有 VS2010 的 vb.net 在 mysql 上插入数据

vb.net - 在 DataGridView 上打开上下文菜单

.net - .NET垃圾收集和 native 线程

c# - ASP.NET Web Api - Startup.cs 不存在

c# - 您可以在静态上下文中引用非静态方法吗?