C# Form_Closed是移除事件处理程序的正确位置吗?

C# Form_Closed是移除事件处理程序的正确位置吗?,c#,memory-management,event-handling,C#,Memory Management,Event Handling,我有一个程序集,它拖放了一个COM互操作VB6.0文本编辑器,并将其用作.NET包装控件。。。 然后在windows窗体的新程序集中,我将程序集拖放到上面并开始使用它,声明它的一个变量并为它分配事件处理程序,例如,如果Assmbley abvoe是namvedMyTextControl,那么在这个windows窗体中,我有一个变量mytxtcntrl,以及一些类似的事件处理程序 mytxtcntrl.TextEditor.ObjectDblClicked += new AxTextEditorL

我有一个程序集,它拖放了一个COM互操作VB6.0文本编辑器,并将其用作.NET包装控件。。。 然后在windows窗体的新程序集中,我将程序集拖放到上面并开始使用它,声明它的一个变量并为它分配事件处理程序,例如,如果Assmbley abvoe是namvedMyTextControl,那么在这个windows窗体中,我有一个变量mytxtcntrl,以及一些类似的事件处理程序

mytxtcntrl.TextEditor.ObjectDblClicked += new AxTextEditorLib._DTextEditorEvents_ObjectDblClickedEventHandler(ctlTEEditor_ObjectDblClicked);
所以现在我甚至担心用“-=”删除这些事件处理程序?或者GC会处理它?
如果我应该手动操作,那么正确的位置是什么?我把它们放在Form_Closed section中,运行了一个内存分析器,它没有任何效果。

不,你不应该这样做。总司令会处理的。您需要担心的唯一地方是当您使用实现了
IDisposable
的类时,或者当您使用
System.Runtime.InteropServices

不,您不应该这样做。总司令会处理的。您需要担心的唯一地方是当您使用实现
IDisposable
的类时,或者当您使用
System.Runtime.InteropServices

时,只有当事件源对象超过事件订阅方时,才需要显式取消订阅事件。不这样做将保留对订阅对象的引用,防止它们被垃圾收集

Winforms是经过精心设计的,以避免这种灾难。您通常会在窗体或用户控件中编写事件处理程序,以侦听子控件触发的事件。这些子控件的生存期与窗体的生存期密切相关,当用户关闭窗体时,它们都会同时被释放。垃圾收集器不会被这一点难倒,而是同时收集所有垃圾

ActiveX控件符合此模式,它将是窗体的子控件,因此在窗体消亡的同一时间消亡。根本不需要显式清理

有几个角落的情况下,这将不会工作所描述的。一个经典的例子是,您自己在自己的代码中删除一个控件,但保持窗体的活动状态。现在,您应该取消订阅任何事件,以允许对该控件进行垃圾收集。最重要的是,您还必须显式调用该控件上的Dispose(),以确保销毁该控件的本机窗口。不这样做会产生一个永久性的泄漏,即使垃圾收集器也无法解决,控件通过其窗口句柄保持活动状态


第二种情况是SystemEvents类。它的事件是静态的,类对象一直存在,直到程序终止。如果您以一种可以关闭的形式使用其事件,而无需终止应用程序,则始终必须显式取消订阅其事件。

只有当事件源对象超过事件订阅方时,才需要显式取消订阅事件。不这样做将保留对订阅对象的引用,防止它们被垃圾收集

Winforms是经过精心设计的,以避免这种灾难。您通常会在窗体或用户控件中编写事件处理程序,以侦听子控件触发的事件。这些子控件的生存期与窗体的生存期密切相关,当用户关闭窗体时,它们都会同时被释放。垃圾收集器不会被这一点难倒,而是同时收集所有垃圾

ActiveX控件符合此模式,它将是窗体的子控件,因此在窗体消亡的同一时间消亡。根本不需要显式清理

有几个角落的情况下,这将不会工作所描述的。一个经典的例子是,您自己在自己的代码中删除一个控件,但保持窗体的活动状态。现在,您应该取消订阅任何事件,以允许对该控件进行垃圾收集。最重要的是,您还必须显式调用该控件上的Dispose(),以确保销毁该控件的本机窗口。不这样做会产生一个永久性的泄漏,即使垃圾收集器也无法解决,控件通过其窗口句柄保持活动状态


第二种情况是SystemEvents类。它的事件是静态的,类对象一直存在,直到程序终止。如果您在表单中使用它的事件,并且该表单可以关闭,而不终止应用程序,则您始终必须显式取消订阅它的事件。

我已经有一段时间没有在.NET中处理ActiveX控件了,但在.NET中曾经存在一个bug,它无法在表单关闭和释放后完全清除ActiveX控件,所以取消订阅可能是个好主意。取消订阅关闭或覆盖窗体的Dispose(bool)应该可以。我有一段时间没有在.NET中处理ActiveX控件了,但是.NET中曾经有一个bug,它阻止它在关闭和释放窗体后完全摆脱ActiveX控件,所以取消订阅可能是个好主意。取消订阅Close或重写窗体的Dispose(bool)应该可以。这并不完全正确,在.NET中内存泄漏的主要原因之一是没有取消注册事件处理程序。“当您使用实现IDisposable的类时”好的,我也有这些,我的一个类正在实现IDisposable,而且它还有一个textEditor类型的变量。在这种情况下,删除事件处理程序的正确位置在哪里?@TrevorPilley有趣的是,你有这方面的任何来源吗?@BDotA你没有完全理解这一点。您永远不需要删除事件处理程序。我的意思是,您必须注意实现IDisposable的类,注意意味着调用Dispose(),而不是删除事件处理程序。这并不完全正确,.NET内存泄漏的主要原因之一是由于没有事件处理程序