简体   繁体   English

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

[英]VB.Net Handles Keyword - Do I need to manually call RemoveHandler?

I am tracking down a memory leak in some applications. 我正在跟踪某些应用程序中的内存泄漏。 Many forms share the same Spellchecker object that therefore out lives any individual form. 许多表单共享同一个Spellchecker对象,因此可以使用任何单独的表单。 I am aware that this can be a cause of memory leaks if the handler events are not removed properly. 我知道,如果未正确删除处理程序事件,这可能是导致内存泄漏的原因。

AddHandler and RemoveHandler make sense to me as it's clear if AddHandler is called then there should be a corresponding RemoveHandler. AddHandler和RemoveHandler对我来说很有意义,因为如果调用AddHandler很明显,那么应该有一个对应的RemoveHandler。 However does the Handles keyword automatically remove the handlers for you? 但是,Handles关键字会自动为您删除处理程序吗?

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

In the above if the spellingContextMenu lives for a long time but the form dies then should the handler be removed manually? 在上面的代码中,如果spellingContextMenu生存时间很长,但是表单死了,那么应该手动删除处理程序吗?

Microsoft's own page offers no guidance on this http://msdn.microsoft.com/en-us/library/6k46st1y.aspx#feedback Microsoft自己的页面对此http://msdn.microsoft.com/zh-cn/library/6k46st1y.aspx#feedback没有提供任何指导

The Handles keyword is based on the assumption that normal event subscription practices can work, with the garbage collector taking care of collecting the event source, event subscriber and delegate object. Handles关键字基于正常事件订阅实践可以正常工作的假设,垃圾回收器负责收集事件源,事件订阅者和委托对象。 Which works fine when the event source doesn't out-live the subscriber. 当事件源没有超出订阅者的寿命时,这种方法就可以正常工作。 A good example is controls inside a Form, when the form is closed then all controls inside of it die as well. 一个很好的例子是窗体内的控件,当窗体关闭时,窗体内的所有控件也会消失。 So the next garbage collection gets rid of all of them, including any delegate objects created by Handles . 因此,下一个垃圾回收将摆脱所有垃圾回收,包括Handles创建的任何委托对象。 No need to explicitly unsubscribe. 无需明确取消订阅。

This doesn't sound like your case if your ContextMenu out-lives the form that uses it. 如果您的ContextMenu超过了使用它的窗体,这听起来不像您的情况。 And you do have a GC problem, your ContextMenu keeps a reference on the form through its event handler(s) so it won't be collected until the menu is collected. 而且您确实遇到了GC问题,您的ContextMenu通过其事件处理程序在表单上保留了引用,因此在收集菜单之前不会收集该引用。 So using Handles is not the proper solution, you really do need to explicitly call AddHandler and RemoveHandler. 因此,使用Handles并不是正确的解决方案,您确实确实需要显式调用AddHandler和RemoveHandler。

Do keep your eyes on the ball, is there really any point at all in not just creating a new ContextMenu for each form? 别注视着球,真的有什么意义,而不仅仅是为每种形式创建一个新的ContextMenu吗? That trivially solves your problem. 轻松解决了您的问题。 An alternative is to not use events but have the form implement an interface. 另一种选择是不使用事件,而是让表单实现一个接口。 You register the form object with the spell checker class, it can listen for the Disposed event to know that it should drop the reference and stop making callbacks through the interface. 您向拼写检查器类注册了表单对象,它可以侦听Disposed事件以知道它应该删除引用并停止通过接口进行回调。

And beware of a bug in VB.NET, if you build the Debug version of an assembly then it will leak a WeakReference for every event that's declared WithEvents if you run it without a debugger attached. 并且要注意VB.NET中的一个错误,如果您生成程序集的Debug版本,则如果在未连接调试器的情况下运行它,则对于声明为WithEvents的每个事件,它都会泄漏WeakReference。 It is one that's created to implement Edit + Continue support, you must deploy the Release build of your assemblies to avoid this leak. 它是为实现Edit + Continue支持而创建的, 必须部署程序集的Release版本才能避免这种泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM