是否有超时的弱引用实现?

时间:2014-12-11 14:13:34

标签: .net weak-references

有时候我需要在一段时间内对内存中的对象进行引用。弱引用允许这样但时间受垃圾收集周期的限制。问题类似于this one,但与.NET有关。

我知道有很多内置了这种功能的缓存,但我不需要使用完整缓存(键值映射)来存储只有一个对象。它宁可是一个单一的“可过期参考”。

我知道我可以自己实现这个,但我正在寻找一个标准的实现(理想情况下集成在框架中,万一我错过了它)

更新

基于@Jeroen Mostert和@dariogriffo的答案,我在这个问题上添加了更多细节。

好的,有两种方法:使用键值缓存或基于计时器的回调。让我们假设有一个对象树,每个对象都有一个缓存值的引用。这些值具有到期超时。假设树节点的数量很大。如果我将每个值存储在MemoryCahce中,则需要为节点分配唯一键,并且通过哈希表搜索来访问它们的值。此外,它还具有向表添加新密钥的一些计算复杂性。另一方面,如果我使用我的自定义WeakReferenceByTimeOut作为@dariogriffo建议那么它没有这样的问题。相反,有一个开销,因为我需要为每个值对象创建一个计时器对象(或者我在内部使用计时器的Task对象)。从我的观点来看,第二种方法更好,但我不确定。

2 个答案:

答案 0 :(得分:2)

据我所知,没有内置任何东西,所以这里实施1分钟

using System.Timers;

public class WeakReferenceByTimeOut<T> where T : class
{
    private Timer _timer;

    public WeakReferenceByTimeOut(T val, int miliseconds)
    {
        Reference = val;
        _timer = new Timer(miliseconds);
        _timer.Elapsed += KillReference;
        _timer.AutoReset = false;
        _timer.Enabled = true;
    }

    public T Reference { get; private set; }

    private void KillReference(object sender, ElapsedEventArgs e)
    {
        _timer.Elapsed -= KillReference;
        _timer.Dispose();
        _timer = null;

        Reference = null;   
    }        
}

答案 1 :(得分:2)

如果一个条目的有效期超过一定时间是很重要的,那么需要某种缓存,即使它只是一个缓存一。最简单的实现(如果你从未将引用设置为其他任何东西)是Task.Delay(...).ContinueWith(t => myWeakReference = null),它不需要额外的类。如果你确实需要能够将引用设置为其他东西(这意味着重置计时器),你需要一个包装类。

顺便说一句,我不建议写一个支持将引用设置为其他东西的类 - 在设置引用和在计时器到期时清除它之间存在固有的竞争条件。如果您需要这样的东西,那么使用策略的经过审查的缓存实现几乎肯定会更好,即使您仅将其用于一个参考。

BCL中没有这样的东西;这是一个不寻常的场景。通常,您可以缓存多个值,或者只要缓存保持在某些内存限制内,您就不关心何时清理引用。如果你有一个带有超时策略的缓存,比如System.Runtime.Caching.MemoryCache,你可以在其中存储WeakReference个实例,这应该实现相同的功能(但你需要仔细检查你从中获取的条目缓存仍然有效。)