【问题标题】:Garbage collection of unreferenced object with live event handler带有实时事件处理程序的未引用对象的垃圾收集
【发布时间】:2013-03-12 19:35:12
【问题描述】:

在下面的程序中...

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.
    }
}

请注意,实例化的Handler 对象没有被引用,尽管它已经订阅了SomeEvent。是否有可能,在程序运行一段时间后,垃圾收集器可能会决定消除 Handler 实例,因此每当引发 parent.SomeEvent 时将不再调用其 parent_SomeEvent 处理程序?

对于我正在编写的应用程序,我需要此说明。有许多类似Handler 的对象如上所示被实例化,没有被引用。 Handler 的中心目的是订阅SomeEvent。没有有用的方法来调用对 Handler 实例的引用,所以我可以不引用它。我在调试时没有遇到任何问题。但是现在我担心当应用程序长时间运行并且垃圾收集器更加活跃时,部署后可能会出现问题。

【问题讨论】:

标签: c# .net


【解决方案1】:

Handler 类的实例化对象将不会被垃圾回收,直到对该对象的所有引用都被删除。

因此,在您取消订阅所有事件处理程序之前,该对象将继续存在。因为订阅的事件处理程序也是将Parent 实例连接到Handler 实例的另一个“引用”。

有没有可能,程序运行一段时间后, 垃圾收集器可能决定消除 Handler 实例及其 因此,parent_SomeEvent 处理程序将不再被调用 parent.SomeEvent 是否引发?

这正是 GC 只从堆中收集“未引用”对象的原因。您的场景将导致未定义的NullReferenceExceptions,完全取决于 GC 何时决定删除对象。幸运的是,情况并非如此:)。

此外,GC 足够智能,可以确定未引用对象的隔离池(未引用岛)。因此,在这种情况下,您的父对象也未被引用,而 GC 将确定整个对象链未被引用(Parent 对象、event 订阅和 handler 对象)并将它们全部收集在一起下一个收集周期。

如果可以,我会推荐this MSDN 文章。让您对 .NET 中垃圾收集的广泛概念有一个很好的概述。在编码时牢记非常有用。

【讨论】:

    【解决方案2】:

    Program 一直存在,它指的是 Parent 的实例,因此 Parent 永远不会被垃圾收集(直到程序结束)。

    Parent 通过其事件处理程序 SomeEvent 保存委托集合,因此其中的任何委托都不会被垃圾回收。

    所以简而言之,不,它不会被垃圾收集。

    【讨论】:

      【解决方案3】:

      当您运行程序时,Parent 类包含对您在Handler 构造函数中创建的EventHandler 委托实例的引用,并且委托实例包含对Handler 实例的引用。因此,只要有对 Parent 实例的引用,Handler 实例就不会被垃圾回收。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-27
        • 2011-03-29
        • 1970-01-01
        • 1970-01-01
        • 2010-11-08
        • 1970-01-01
        • 2011-07-03
        • 1970-01-01
        相关资源
        最近更新 更多