我正在处理一个具有多个窗体的C#应用程序。
当我打开其中一个窗体时,我添加了一个事件侦听器,如下所示:SomeClass.MotionCompleted += new EventHandler(HandlerMethod);
。MotionCompleted
事件是静态事件。
我注意到,关闭此窗体后,当事件发生时,仍然会调用HandlerMethod
,这会导致异常,因为它试图更新窗体上不再存在的内容。
即使表单不再存在,事件侦听器如何存在并响应事件?一旦调用form.Close()
或this.Close()
,是否应该自动取消事件侦听器的挂钩,使它们不再被调用?
9条答案
按热度按时间hmae6n7t1#
这就是静态事件的邪恶!:)你有一个managed leak在那里。
重写窗体的OnClosing并注销处理程序:
qlfbtfca2#
这篇文章展示了许多关于C#中事件的提示:
https://csharpindepth.com/articles/Events
3qpi33ja3#
要添加到所有重复的答案中,您也可以通过以下方式取消挂钩:
无论使用
-= HandlerMethod
还是-= new EventHandler(HandlerMethod)
,输出的汇编代码都是相同的。jgovgodb4#
只要把“+”改成“-”
gz5pxeao5#
您可以使用以下示例代码:
但是,您必须小心地将事件从包含
HandlerMethod
的对象的同一个示例(注册它的示例)中解除挂钩。btxsgosb6#
您需要像这样手动取消事件挂钩:
SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
wlsrxk517#
不完全是。因为事件处理程序仍然存在,所以垃圾收集器不会收集表单。静态事件处理程序不会自己脱钩。您可以脱钩表单onClosing方法中的任何赋值事件,如下所示:
之后一切都应该工作。
y1aodyip8#
事件被强烈引用:除非您显式取消引用它们,否则它们不能被垃圾收集。
这就是为什么我建议你写一个subscribe和一个unsubscribe方法,它们将完成它们的工作并集中这些钩子(如果你不释放它们,这将导致内存泄漏)
b09cbbtk9#
您必须手动脱钩: