在我的应用程序中,我有Dictionary<int, WeakReference<Foo>>
来缓存Foo
从文件中读取的内容,其中键是文件中的索引。由于Foo
是可变的,因此只要对该索引处的Foo
进行任何引用,缓存条目就必须保持活动状态(以便任何持有者以及从{ {1}}来源)。
我希望在Foo
完全未引用后删除Dictionary
条目。我最初的想法是将Foo
的终结器从缓存中移除,但是当在缓存插入时触发GC时,这导致内部状态不一致。我试图理解终结器不能用于托管内存的概念。有没有办法做到这一点?
答案 0 :(得分:1)
在我看来,您正在寻找的是ConditionalWeakTable<TKey, TValue>
,您将Foo
作为关键字存储,而不是您的价值:
ConditionalWeakTable类与其他类不同 集合对象在其管理对象的生命周期中 存储在集合中。通常,当一个对象存储在一个 收集,它的寿命持续到它被删除(并且没有 对对象的附加引用)或直到集合对象 本身就被摧毁了但是,在ConditionalWeakTable类中,向表中添加键/值对无法确保 密钥将持续存在,即使它可以直接从a到达 存储在表中的值(例如,如果表包含一个键, A,值为V1,第二个键B,其值为P2 提及A)。相反, ConditionalWeakTable 没有其他人就会自动删除键/值条目 表格之外存在对密钥的引用。
答案 1 :(得分:0)
我最后通过一个项目来解决这个问题,我打电话给BackgroundFinalizer(github上的来源)。从本质上讲,这可以让你定义一个&#34;终结者&#34;在垃圾收集期间不运行,而是在后台运行。所以在我的特殊情况下,当Foo
被垃圾收集时,从缓存中删除条目的函数被安排在独立于GC的工作线程中运行,因此我们避免在终结器中阻塞任何情况或内部状态不一致。
答案 2 :(得分:0)
由于取消引用后无法自动删除Dictionary
条目,所以另一个想法是,一旦了解该知识,就可以通过编写如下这样的缓存获取函数将其自己删除:< / p>
private readonly Dictionary<int,WeakReference<Foo>> _dict;
public bool TryGetItem(int key, out Foo item) {
if (_dict.TryGetvalue(key, out var wr)) {
if (wr.TryGetTarget(out item))
return true;
else
// The weak reference is dead. We remove the dictionary entry.
_dict.Remove(key);
}
return false;
}