有时候我需要在一段时间内对内存中的对象进行引用。弱引用允许这样但时间受垃圾收集周期的限制。问题类似于this one,但与.NET有关。
我知道有很多内置了这种功能的缓存,但我不需要使用完整缓存(键值映射)来存储只有一个对象。它宁可是一个单一的“可过期参考”。
我知道我可以自己实现这个,但我正在寻找一个标准的实现(理想情况下集成在框架中,万一我错过了它)
更新
基于@Jeroen Mostert和@dariogriffo的答案,我在这个问题上添加了更多细节。
好的,有两种方法:使用键值缓存或基于计时器的回调。让我们假设有一个对象树,每个对象都有一个缓存值的引用。这些值具有到期超时。假设树节点的数量很大。如果我将每个值存储在MemoryCahce中,则需要为节点分配唯一键,并且通过哈希表搜索来访问它们的值。此外,它还具有向表添加新密钥的一些计算复杂性。另一方面,如果我使用我的自定义WeakReferenceByTimeOut
作为@dariogriffo建议那么它没有这样的问题。相反,有一个开销,因为我需要为每个值对象创建一个计时器对象(或者我在内部使用计时器的Task对象)。从我的观点来看,第二种方法更好,但我不确定。
答案 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
个实例,这应该实现相同的功能(但你需要仔细检查你从中获取的条目缓存仍然有效。)