1

MyUserControl我有一些会引发事件的类(用户控件) 。

我以一种形式使用它MyForm,因为某些原因,我被迫使用它AddHandler而不是WithEvents<>Handlespair。

我在方法中使用AddHandler了 s 。MyForm_Load

现在。添加处理程序是可以的,现在的问题是在哪里删除这个处理程序。是否应该在FinalizeMyForm的方法中完成?啦啦

Protected Overrides Sub Finalize()
  RemoveHandler _myCtrl.Action1Performed, AddressOf MyControl_Action1Performed  
  RemoveHandler _myCtrl.Action2Performed, AddressOf MyControl_Action2Performed  
  RemoveHandler _myCtrl.Action3Performed, AddressOf MyControl_Action3Performed  
End Sub
4

4 回答 4

5

当容器控件(例如您的表单)被释放时,它的所有事件处理程序将被自动删除和释放。这种清理会自动为您发生,因为您的用户控件及其容器表单都不存在了。

您真正需要担心调用的唯一时间RemoveHandler是,如果您将事件处理程序连接到预期具有比其容器更长的生命周期的对象。在这种情况下,可能会造成内存泄漏,因为只要订阅了该处理程序,该对象就不能被垃圾收集。您可以在 Tess Ferrandez 的博客上阅读更全面的案例研究。如果两个对象同时“超出范围”,这不是问题。

编辑:如果您仍然觉得您绝对需要删除处理程序(也许您是强迫症?),您可以继续并在表单的Dispose方法中执行此操作。纯粹主义者可能会拒绝使用IDisposable类似这样的东西,但您不会看到任何不良结果。不过,您确实要确保不Finalize为此实现该方法。没有意义:在没有更多对该对象的强引用之前,不会调用终结器方法,但未能调用的唯一可能RemoveHandler危害是容器将持有对该对象的引用的时间超过必要的时间。您试图在Finalize方法中删除事件处理程序是在自欺欺人。

还要记住,你在哪里做这件事并不重要,因为AddHandler/的目的RemoveHandler是允许你动态地添加和删除事件处理程序。您可以在您想要的代码中的任何位置调用它们。

于 2011-01-28T10:43:29.063 回答
1

假设您的 Form 是 UserControl(s) 的所有者,您根本不需要任何清理。

如果您有像AddressOf OtherObject.Action1Performed和 OtherObject 这样的处理程序比 Form 寿命更长,那么您应该删除该处理程序。


编辑:

关于 'where' :不在a 中Sub Finalize

您可以使用 Dispose() 方法(在 C# 中,您可以将其从 Designer 文件中移动)。否则,使用 FormClosed 事件。

这里不需要终结器,但它确实带来了相当大的成本。

于 2011-01-28T10:41:09.403 回答
0

对象的终结器对于清理该对象的事件订阅毫无用处。它不会触发,直到对象订阅的所有事件的所有发布者本身都超出范围,一旦发生,清理事件的问题将变得没有意义。为此目的创建终结器实际上会适得其反,因为可终结对象将延迟其自身以及它持有直接或间接引用的任何对象的垃圾收集。

我认为按照习惯清理事件订阅是一种好习惯。如果发布者和订阅者具有相同的生命周期,则可能会将事件订阅视为托管资源,但来自长期对象的事件是非托管资源. 如果它们没有在其他地方清理,则应该在 Dispose 中清理它们(并且 Dispose 应该是在其他地方清理的“支持”)。虽然可以忽略对短期对象的事件订阅,但这种做法需要确定哪些事件发布者是或可能是长期存在的。另请注意,当对象超出范围时,定期取消订阅事件将限制错过偶然事件时可能造成的损害。如果来自所谓的短寿命对象的事件被丢弃,但一个长寿命对象的事件也被丢弃,那么在长寿命对象之前,没有一个短寿命对象可以进行垃圾收集。

于 2011-02-01T20:04:48.270 回答
0

不知道为什么要删除处理程序,除非您在下一个回帖中不再需要它们并且您有条件地在页面加载时再次设置它们,否则如果您在每次回帖中使用它们,您应该让 GC 处理处置

于 2011-01-28T10:39:59.760 回答