【问题标题】:.NET: Any way to tell when an object is disposed/garbage collected?.NET:有什么方法可以判断对象何时被处理/垃圾收集?
【发布时间】:2012-08-25 04:20:45
【问题描述】:

给定一个对象,有没有办法在该对象被垃圾回收时得到通知?

我正在尝试让 C# 扩展方法的行为更像 mixins(特别是在添加日志记录方面)。所以基本上每个对象都会获得一个新的 Logger() 方法,该方法返回一个 ILog,该 ILog 根据作为扩展方法目标的对象创建和缓存。

工作得非常好,唯一的担心显然是在一个对象消失后,它的记录器可能会停留相当长的一段时间。我当然可以设置一些定期机制来扫描记录器缓存并清除它,但我更愿意设置一些垃圾收集通知,以便了解系统何时不再使用我的对象。

有人知道怎么做吗?

【问题讨论】:

    标签: .net garbage-collection


    【解决方案1】:

    我认为这里通常要做的是维护WeakReferences 的列表。使用弱引用,您可以通过检查 IsAlive 属性来判断您所引用的对象是否已被垃圾回收。

    【讨论】:

      【解决方案2】:

      在 .net 4.0 中,有一个类型 ConditionalWeakTable 可用于在任意对象符合最终确定条件时请求通知,尽管有点笨拙。如果ConditionalWeakTable 包含将一个对象(例如创建的第 451 个对象)映射到另一个对象(例如创建的第 730 个对象)的条目,那么只要该条目保留在表中,并且根引用既存在于表中,也存在于对象#451,该表将被视为对对象#730 的根引用。如果对象#451 不存在根引用,则该表将不再是对象#730 的根引用。

      因此,如果对象#730 持有对表的引用,并且对象#730 存在于表之外,则对象#730 将与对象#451 一起成为最终确定对象。如果对象#730 覆盖Finalize(),则该覆盖可用作通知对象#451 已符合完成条件。

      请注意,对象 #730 的终结器只会触发一次,即使对象 #451 自己复活并重新注册以进行终结也是如此。可以编写代码在对象 #451 真正死亡并被掩埋时触发通知,即使它首先复活了几次,但没有特别干净的方法可以这样做。

      【讨论】:

      • 如果有一个类来管理这个并抽象出丑陋的东西,为调用客户端提供一个漂亮的接口,FWIW,那就太棒了。另外,从我读到的,听起来一个物体只能复活一次?那准确吗?来源:philosophicalgeek.com/2014/08/20/…
      【解决方案3】:

      The destructor 在 GC 期间被调用。

      【讨论】:

      • 这很有趣。我总是听到他们被称为“终结者”。是命名法改变了,还是我一直都弄错了?
      • 我认为这取决于语言。在 C# 中,destructor 似乎是指实现 finalization 的语言结构。然而,在 C++/CLI 中,称为 destructor 的语言构造(例如 ~class() {...})实际上实现了 IDispose 接口,同时还有一种称为 finalizer 的新语言构造(例如!class() {...})与C#中的析构函数相同。
      • 是的,但这意味着我必须创建一个调用类似 this.ReleaseLogger() 的析构函数。不错的主意,但我宁愿避免。
      • @Darin:实际上析构函数是在之后被GC检测到对象不可达,但是之前对象内存实际上被回收(并且只有当对象仍然无法访问时才会回收内存,因为析构函数有能力使死去的对象复活)。
      猜你喜欢
      • 2015-04-22
      • 1970-01-01
      • 2011-10-12
      • 2017-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-08
      • 2017-05-17
      相关资源
      最近更新 更多