【问题标题】:Does garbage collector clear objects subscribed to events?垃圾收集器是否清除订阅事件的对象?
【发布时间】:2009-05-29 21:44:33
【问题描述】:

如果我执行以下操作:

public class Test
{
    public static void Main()
    {
        List<Person> persons = new List<Person> { new Person() };

        persons[0].Sneezing += new EventHandler(Person_Sneezing);

        persons = null;
    }

    public static void Person_Sneezing(object sender, EventArgs e)
    {
        (sender as Person).CoverFace();
    }
}

在 person[0] 中的人是否仍然存在于内存中,因为它的 Sneezing 委托引用了 Person_Sneezing 方法,还是被 GC 收集了?

【问题讨论】:

    标签: c# memory-leaks garbage-collection


    【解决方案1】:

    这将由 GC 收集。要保存在内存中,对象必须直接或间接地被 ...

    1. 堆栈上的值
    2. 植根于强大的 GC 句柄的值
    3. 我暂时没有想到一两个角落案例

    这不适用于persons[0] 处的对象。所以它会被收集起来。

    这当然是假设 Person() 的构造函数没有做任何有趣的事情,比如将自身添加到 ThreadLocalStorage。

    【讨论】:

      【解决方案2】:

      你已经成功了一半;如果它是 其他方式,这将是内存泄漏。也就是说,如果它看起来像这样:

      public class Test
      {
          public void HookupStuff()
          {
              List<Person> persons = new List<Person> { new Person() };
      
              this.EventHappened += new EventHandler(persons[0].SomeMethod);
              // persons[0].Sneezing += new EventHandler(Person_Sneezing);
      
              persons = null;
          }
      }
      

      现在persons[0] 将继续存在,即使您取消了persons,因为父类有一个对其方法的引用。

      【讨论】:

      • 你会称之为泄漏吗?如果测试顺利,persons[0] 也会如此。
      • 当然,但是最终一切都会消失——最糟糕的是,当您的应用程序退出时,一切都会消失!当您认为它会消失时,如果它不会消失,我会称之为泄漏。
      • (另外,如果你没有再次提到person[0],你将很难找回它,所以它基本上被泄露到虚无中。)
      • 有关这如何成为泄漏的示例,请在不先将 Visible 设置为 false 的情况下销毁显示在表单上的 ToolStrip。您会发现(如果您使用内存分析器)它仍然存在 - 因为当主题更改时,Windows 会引发一个事件来通知所有主题控件,并为此维护对 ToolStrip 的引用。 (如果你想一想,你就会明白我为什么知道这个。提示:我不想知道。)
      【解决方案3】:

      除了你已经得到的答案,你需要在更现实的例子中小心。

      如果您的应用程序有一个在程序运行期间一直存在的主窗口,并且您经常创建“短期”对象,将它们的方法用于主窗口上的事件,那么您必须从这些事件中删除对象您不再需要它们,因为否则这些对象根本不会“短暂”存在 - 它们将与主窗口一样存在,即直到用户关闭应用程序。有效的结果将等同于内存泄漏。

      如果你让短期对象的类实现IDisposable会有所帮助,这样你就可以从Dispose中的事件中删除,然后确保在你想丢弃一个对象时调用dispose。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多