代码之家  ›  专栏  ›  技术社区  ›  Prince Ashitaka

不知情事件是内存泄漏吗?

c#
  •  6
  • Prince Ashitaka  · 技术社区  · 14 年前

    如果是,是否有一种方法可以对所有有线事件进行全局解绑

    编辑: 比如说。我有一些对象,每个对象都标记了一个事件,比如 orm.NatureChanged += Nature_Changed; 我在创建每个orm实例时标记这些事件。如果我不是不明智的话 orm.NatureChanged -= Nature_Changed; 会导致内存泄漏吗?

    4 回复  |  直到 14 年前
        1
  •  5
  •   kemiller2002    14 年前

    不,因为当您取消激活一个事件时,连接到该事件的委托(它是一个对象)不再是根,并且当GC认为合适时将被收集。当然,这是假设事件委托没有附加到多个处理程序,在这种情况下,只有从所有事件中取消对它的访问,才会收集它。

        2
  •  7
  •   Adam Robinson    14 年前

    1. 是否需要对没有任何委托的事件执行某些操作?
    2. 事件是否可以阻止对象被垃圾收集器清除?

    第一个问题的答案是“不”。往前走,这里没什么可看的。

    可以 导致对象在内存中保留的时间比预期的长,因为这种可达性对于用户(开发人员)来说是透明的,因为委托的构造方式是这样的。

    换句话说,假设我有两个对象:生产者和消费者。生产者触发消费者…消费的事件。

    public class Producer
    {
        public event EventHandler OmgIDidSomething;
    }
    
    public class Consumer
    {
        public void AttachTo(Producer producer)
        {
            producer.OmgIDidSomething += new EventHandler(producer_OmgIDidSomething);
        }
    
        private void producer_OmgIDidSomething(object sender, EventArgs e)
        {
            // ...
        }
    }
    

    在本例中,任何 Consumer 哪里 AttachTo Producer 它附加到的有资格收集,因为 OmgIDidSomething 事件引用了的实例 它对应的。

        3
  •  2
  •   supercat    14 年前

    不知情的 可能会导致内存泄漏,答案是,如果保存事件委托的对象的实际生存期比委托引用的对象的有效生存期长得多,则会导致内存泄漏。例如,如果集合的枚举器钩住了CollectionChanged事件,并且有人要获取枚举器而从不处理它们,那么每次枚举集合(而不处理枚举器)时,都会创建一个新的枚举器对象,该对象将与基础集合一样长时间地保留在内存中。

        4
  •  2
  •   Community Egal    7 年前

    这不是内存泄漏,它只是没有将任何处理程序挂接到该事件,如果它们没有连接、自动或其他方式。所以这件事不会对任何人开火,会被清理干净,生活还会继续。

    How do events cause memory leaks in C# and how do Weak References help mitigate that?

    请参见以下背景信息: What does AutoEventWireUp page property mean?