【问题标题】:Make an object lifetime depend on another without the latter referencing the former使一个对象的生命周期依赖于另一个而不是后者引用前者
【发布时间】:2013-12-04 14:21:17
【问题描述】:

我正在开发一个类库。

一个实用方法被频繁调用,并被传递给一个复杂的第三方对象。 该方法使用来自模型的数据,这些数据收集起来很耗时。 因此,出于性能原因,我想将数据缓存到 Dictionary 类中,以便一次性收集必要的数据,然后将其用于所有连续调用。

但是,出于多种原因,要求库的使用者维护一个可以存储字典的对象实例并不方便。

是否可以创建一个可以像静态字段一样访问的对象,但如果收集到另一个(指定的)对象,则该对象会被收集?

准码:

SomeMethodRequiringALotOfDataFromHugeSystem(detector detectorInHugeSystem)
{
   //access HugeSystem from a property in the dectector.
   //find if Huge System already has a Dictioary.
   //Build a Dictionary from data in Huge system if necessary.

   //(Not possible?) Associate the dictionary to the HugeSystem object instance so that Dictionary will be collected if HugeSystem instance is collected.

   // Perform time efficient task based on Dictionary.
}

【问题讨论】:

  • 在什么情况下会收集到探测器对象?
  • 坏主意,不要这样做。您需要一个计时器来定期检查客户端对象是否尚未被收集。你用 Wea​​kReference.IsAlive 做什么。
  • 我正在通过探测器到达“巨大的系统”。该方法需要这些数据才能为检测器提供服务。但是,由于构建成本高昂,我想在处理同一个“庞大系统”中的各种检测器时在连续调用中重用缓存。

标签: .net c#-4.0 memory garbage-collection


【解决方案1】:

我认为您可以使用ConditionalWeakTable 来解决这个问题。 它主要是为语言编译器设计的,但没有什么能阻止你将它用于其他目的。

ConditionalWeakTable 只要在表外不存在对某个键的其他引用,就会自动删除键/值条目

因此,如果您想创建一个在收集对象 B 时将收集的对象 A,您可以将 {key=B, value=A} 添加到 ConditionalWeakTable。 您可以随时使用yourTable.TryGetValue(B) 访问 A。确保在其他任何地方都没有对 A 的任何其他永久引用,那么在收集 B 时应该收集 A。

(请记住,垃圾收集器不会在对象不再被引用后立即收集它们。尤其是大对象可能会自动在第 2 代结束,这只是偶尔收集)

另请参阅stackoverflow answer 关于 ConditionalWeakTable 的使用

【讨论】:

  • 这看起来很有希望。我从来没听说过。谢谢。
【解决方案2】:

WeakReference是专门为这种情况制作的。

弱引用允许垃圾收集器收集对象,同时仍允许应用程序访问该对象。如果您需要该对象,您仍然可以获得对它的强引用并阻止它被收集。

【讨论】:

  • 情况正好相反。弱引用允许我引用一个对象,而不会阻止它被收集。我的问题是:我可以创建一个对象 A,在 B 不知道 A 的情况下收集对象 B 时将其收集吗?
  • @Tormod 没有办法按照你想象的方式去做。唯一的方法是为每个 HugeObject 的字典保留 WeakReference,并希望 GC 不会过多地触及它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-20
  • 1970-01-01
  • 1970-01-01
  • 2016-12-13
  • 1970-01-01
相关资源
最近更新 更多