事件处理程序是否阻止垃圾收集发生?

时间:2008-11-18 09:35:33

标签: c# .net event-handling garbage-collection

如果我有以下代码:

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass = null;

pClass会被垃圾收集吗?或者它会在它们发生的时候仍然停止发射?我是否需要执行以下操作才能进行垃圾回收?

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass.MyEvent -= MyFunction;
pClass = null;

4 个答案:

答案 0 :(得分:192)

对于特定问题“将pClass收集垃圾”:事件订阅对pClass(作为发布者)的集合没有影响。

对于一般的GC(特别是目标):它取决于MyFunction是静态的还是基于实例的。

实例方法的委托(例如事件订阅)包括对实例的引用。所以,是的,事件订阅将阻止GC。但是,只要发布事件的对象(上面的pClass)有资格进行收集,这就不再是一个问题。

请注意,这是单向的;即如果我们有:

publisher.SomeEvent += target.SomeHandler;

然后“发布者”会保持“目标”活着,但“目标”不会让“发布者”保持活力。

所以不是:如果要收集pClass,则无需取消订阅听众。但是,如果pClass是长寿命的(比MyFunction的实例长),那么pClass可以使该实例保持活动状态,因此如果您希望收集目标,则 必须取消订阅。

因此,静态事件与基于实例的处理程序一起使用时非常危险。

答案 1 :(得分:7)

是的,pClass将被垃圾收集。事件订阅并不意味着pClass存在任何引用。

所以不,你不必分离处理程序,以便pClass被垃圾收集。

答案 2 :(得分:7)

当一块内存不再被引用时,它就成了垃圾收集的候选者。当您的类的实例超出范围时,您的程序将不再引用它。它不再使用,因此可以安全地收集。

如果你不确定某些东西会被收集,请问自己以下问题:是否仍然存在对它的引用?事件处理程序由对象实例引用,而不是相反。

答案 3 :(得分:0)

pClass将被垃圾收集。但是,如果上面的代码段位于另一个类中,则如果未将pClass设置为null,则可能无法清除该类的实例。