如果对象被垃圾回收,如何获得通知
本文关键字:何获得 通知 对象 如果 | 更新日期: 2023-09-27 18:20:05
短版本:
对于缓存类,如果对象被垃圾收集,我需要得到通知(从缓存中删除相应的条目)。最好的方法是什么?从析构函数发送事件?
长版本:
我正在编写一个缓存/内存器,用于获取一个巨大参数树对象和许多小值类型参数的函数,例如
double myFunc(HugeParTree parTree, int dynPar1, double dynPar2)
我想以以下方式缓存这些函数:
- 元组的缓存结果(parTree.GGUID、dynPar1、dynPar 2…)
- 每当
parTree
发生变化时(这种情况很少发生),所有相应的缓存条目都会被删除(通过Observer模式)。(parTree.Equals()
太贵了;它比较了100多种值类型)
代码现在看起来是这样的(对于一个值参数):
public class CachedFunction1ObsPar1Par<TRet, TObsPar1, TPar1>
where TObsPar1 : IObservable, IProvideGUID
{
public delegate TRet ValueCalculator(TObsPar1 obsPar1, TPar1 par1);
public CachedFunction1ObsPar1Par(ValueCalculator calc)
{
_calc = calc;
}
#region members
private ValueCalculator _calc;
private Dictionary<Guid, Dictionary<TPar1, TRet>> _cache =
new Dictionary<Guid, Dictionary<TPar1,TRet>>();
#endregion
public TRet value(TObsPar1 obsPar1, TPar1 par1)
{
TRet result;
bool cacheHit = checkCache(obsPar1, par1, out result);
if (cacheHit)
{
Debug.Assert(result.Equals(_calc(obsPar1, par1)));
return result;
}
else
{
result = _calc(obsPar1, par1);
_cache[obsPar1.GUID].Add(par1, result);
return result;
}
}
private bool checkCache(TObsPar1 obsPar1, TPar1 par1, out TRet result)
{
if (!_cache.ContainsKey(obsPar1.GUID))
{
_cache.Add(obsPar1.GUID, new Dictionary<TPar1, TRet>());
obsPar1._changed += this.invalidateCache;
}
Dictionary<TPar1, TRet> guidCache = _cache[obsPar1.GUID];
bool success = guidCache.TryGetValue(par1, out result);
return success;
}
private void invalidateCache(object sender)
{
TObsPar1 obsPar = (TObsPar1)sender;
_cache.Remove(obsPar.GUID);
obsPar._changed -= this.invalidateCache;
}
}
我还没有对此进行测试,因为我仍然存在这样的问题,即在不再使用相应的parTree之后,缓存条目永远不会被删除。我希望有一个同步解决方案,不用对非常旧的缓存条目重复"扫描"。
对于缓存类,如果对象是垃圾,我需要得到通知collected(从我的缓存中删除相应的条目)。什么是这样做的最佳方式?从析构函数发送事件?
如果您的缓存包含正常(强)引用,则永远不会收集这些项。
如果您的缓存中包含WeakReferences,则无需删除任何内容。
您可以定义一个接口"ICacheable",该接口必须由缓存中的对象实现。在接口RemoveFromCache()
的方法中,您可以在缓存中搜索其子对象并删除它们。
当您从缓存中删除一个项时,请测试该项的接口并调用RemoveFromCache()
。
这与IDisposable类似。
垃圾回收不是一件可以指望的事情,因为你永远不知道它什么时候会运行。
Henk已经提到了您的需求中的缺陷。
但是,只是为了回答你的问题。要知道对象何时被垃圾收集,可以为该对象编写析构函数。
~YourClass();
根据MSDN:
在对象变为不可访问
尽管从不建议依赖GC或析构函数。