【问题标题】:Do event handlers stop garbage collection from occurring?事件处理程序会阻止垃圾收集的发生吗?
【发布时间】:2010-09-22 19:58:59
【问题描述】:

如果我有以下代码:

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

pClass 会被垃圾回收吗?或者它是否会在事件发生时仍然触发它的事件?为了允许垃圾收集,我需要执行以下操作吗?

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

【问题讨论】:

  • 我将暂时向对此问题感兴趣的读者建议,熟悉轻量级事件/弱事件模式可能是值得的,它们不会阻止垃圾收集的发生。这个主题的一个很好的 SO 引导是 stackoverflow.com/questions/185931/…
  • 后人注意:将引用设置为 null 只是通过将引用范围扩展一行来延迟垃圾收集器。 .NET 不是 VB6。

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


【解决方案1】:

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

因此,不,您不必分离处理程序即可对 pClass 进行垃圾收集。

【讨论】:

    【解决方案2】:

    pClass 将被垃圾回收。但是,如果上面的代码 sn-p 在另一个类中,如果不将pClass 设置为null,则可能不会清除该类的实例。

    【讨论】:

      【解决方案3】:

      针对具体问题“PClass是否会被垃圾回收”:事件订阅对pClass的回收没有影响(作为发布者)。

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

      实例方法的委托(例如事件订阅)包括对该实例的引用。所以是的,事件订阅将阻止 GC。但是,一旦发布事件的对象(上面的 pClass)符合收集条件,这将不再是问题。

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

      publisher.SomeEvent += target.SomeHandler;
      

      那么“publisher”将使“target”保持活跃,但“target”不会让“publisher”保持活跃。

      所以不:如果无论如何都要收集 pClass,则无需取消订阅侦听器。但是,如果 pClass 是长期存在的(比具有 MyFunction 的实例长),那么 pClass 可以使该实例保持活动状态,因此如果您希望收集目标,则需要取消订阅。

      但是,由于这个原因,静态事件在与基于实例的处理程序一起使用时非常危险。

      【讨论】:

      • 好吧,如果问题是“pClass 是否会被垃圾回收”,那么“这取决于是否...”的答案实际上并不正确。正如 Marc 自己进一步指出的那样,它不依赖于任何东西。
      • @Tor - 很公平 - 我会澄清
      • 虽然事件订阅委托只指向一个方向,但如果订阅者想要在完成事件后取消订阅,则需要某种形式的对发布者的引用。可能是WeakReference,在某些情况下这可能是个好主意,但通常情况下它会很强大。
      • 一个很好的答案,因为它还解决了问题的另一半(没有被问到):publisher 将阻止 subscriber被 GC 处理。
      • 是的,正如@BobSammers 所说,如果像窗体/窗口这样的短生命周期实例订阅像单例这样的长生命周期服务,它提供数据示例:Singleton 然后保留一个引用,因此即使我们认为它们已卸载,对象也会保留在内存中!所以在使用事件时要非常小心。我们为我们的大软件滥用了事件,之后很难解决。
      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 2015-05-04
        • 1970-01-01
        • 1970-01-01
        • 2015-10-08
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        • 2013-12-31
        • 1970-01-01
        相关资源
        最近更新 更多