1

我有一个程序集,其中拖放了一个 COM Interop VB 6.0 文本编辑器,并将其用作 .NET 包装控件...然后在一个新的程序集中,它是一个 Windows 窗体,我将程序集拖放到上面并开始使用它,声明它的一个变量并为其分配事件处理程序,例如,如果 Assmbley abvoe 被命名为MyTextControl,那么在这个 Windows 窗体中,我有一个mytxtcntrl变量和一些事件处理程序,例如

mytxtcntrl.TextEditor.ObjectDblClicked += new AxTextEditorLib._DTextEditorEvents_ObjectDblClickedEventHandler(ctlTEEditor_ObjectDblClicked);

所以现在 Sholud 我什至担心用 "-=" 删除这些事件处理程序?还是 GC 会处理它?如果我应该手动操作,那么正确的操作位置是什么?我把它们放在 Form_Closed 部分并运行内存分析器,它没有任何效果。

4

2 回答 2

3

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

Winforms 是经过精心设计的,以避免发生这种事故。您通常会在表单或用户控件中编写事件处理程序来侦听由子控件触发的事件。这些子控件的生命周期与窗体的生命周期密切相关,它们都在用户关闭窗体的同时被释放。垃圾收集器不会被这件事难住,会同时收集它们。

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

在某些极端情况下,这不会像描述的那样工作。一个经典的方法是您自己在自己的代码中删除一个控件,但保持表单处于活动状态。现在您应该取消订阅任何事件以允许对该控件进行垃圾收集。最重要的是,您还必须在控件上显式调用 Dispose() 以确保销毁它的本机窗口。不这样做会产生甚至垃圾收集器都无法解决的永久泄漏,控件通过其窗口句柄保持活动状态。

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

于 2012-12-11T16:53:49.537 回答
2

不,你不应该。GC 会处理它。唯一需要担心“丢弃”对象的地方是,当您使用实现的类IDisposable或使用System.Runtime.InteropServices.

于 2012-12-11T16:29:13.550 回答