如果对象被垃圾回收,如何获得通知

本文关键字:何获得 通知 对象 如果 | 更新日期: 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或析构函数。