C# 使用活动事件处理程序对未引用对象进行垃圾收集
在下面的程序中C# 使用活动事件处理程序对未引用对象进行垃圾收集,c#,.net,C#,.net,在下面的程序中 using System; class Program { static Parent parent; static void Main( string[] args ) { parent = new Parent(); // The program hereafter runs for a long time and occasionally // causes parent.SomeEvent to
using System;
class Program
{
static Parent parent;
static void Main( string[] args )
{
parent = new Parent();
// The program hereafter runs for a long time and occasionally
// causes parent.SomeEvent to be raised.
}
}
class Parent
{
public event EventHandler SomeEvent;
public Parent()
{
new Handler( this );
}
}
class Handler
{
public Handler( Parent parent )
{
parent.SomeEvent += parent_SomeEvent;
}
void parent_SomeEvent( object sender, EventArgs e )
{
// Does something important here.
}
}
请注意,实例化的处理程序
对象未被引用,尽管它已订阅SomeEvent
。在程序运行一段时间后,垃圾收集器是否可能决定删除处理程序
实例,因此每当引发parent.SomeEvent
时,将不再调用其parent\u SomeEvent
处理程序
我需要这个澄清我写的应用程序。如上图所示,有许多类似于处理程序的对象被实例化,而没有被引用。
Handler
的主要目的是订阅SomeEvent
。没有任何有用的方法可以调用对处理程序
实例的引用,因此我可以不引用它。调试时我没有遇到任何问题。但现在我担心,当应用程序长时间运行且垃圾收集器更活跃时,部署后可能会出现问题。在删除对该对象的所有引用之前,不会对处理程序的实例化对象进行垃圾收集
因此,在您取消订阅所有事件处理程序之前,对象将处于活动状态。因为订阅的事件处理程序也是另一个“引用”,它将父类
实例连接到处理程序
实例
程序运行一段时间后,是否可能
垃圾收集器可能决定删除处理程序实例及其
因此,无论何时都不再调用父事件处理程序
是否引发parent.SomeEvent
这正是GC只从堆中收集“未引用”对象的原因。您的场景将导致未定义的NullReferenceException
s,完全取决于GC决定何时删除对象。幸运的是,情况并非如此:)
此外,GC足够智能,可以确定未引用对象的孤立池(未引用孤岛)。因此,在场景中,父对象也未被引用,GC将确定整个对象链未被引用(父对象<代码>父对象<代码>对象、<代码>事件代码>订阅和<代码>处理程序代码>对象),并将在下一个收集周期中收集它们
如果可以的话,我推荐这篇文章。让您很好地概括了.NET中垃圾收集的广泛概念。编码时要记住这一点非常有用。程序始终存在,它引用的是父对象的一个实例,因此父对象将永远不会被垃圾收集(直到程序结束)
Parent通过其事件处理程序SomeEvent保存代理集合,因此不会对其中的任何代理进行垃圾收集
因此,简而言之,不,它不会被垃圾收集。当您运行程序时,父类
持有对您在处理程序
构造函数中创建的事件处理程序
委托实例的引用,委托实例持有对处理程序
实例的引用。因此,只要有对父实例的引用,就不会对处理程序实例进行垃圾收集。请查看这篇文章以获得更深入的解释