짧은 버전 :
캐시 클래스의 경우 개체가 가비지 수집되었는지 (캐시에서 해당 항목을 제거하기 위해) 알려야합니다. 그렇게하는 가장 좋은 방법은 무엇입니까? 소멸자로부터 이벤트 보내기?개체가 가비지 수집되는 경우 알림을받는 방법?
긴 버전 :
내가 예를 들어, 하나의 큰 매개 변수 트리 객체와 많은 작은 값 유형 매개 변수를 취할 기능을위한 cacher/memoizer을 쓰고,
double myFunc(HugeParTree parTree, int dynPar1, double dynPar2)
나는 이러한 기능을 캐시 할 다음과 같은 방법으로 : 튜플 (parTree.GUID, dynPar1, dynPar2, ...)
- 캐시 결과 ver
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 후 제거되지는 결코 캐시 문제를 가지고 더 이상 사용되지 않습니다. 아주 오래된 캐시 항목에 대해 반복적 인 "스캔"없이 동기식 솔루션을 좋아할 것입니다.
그러나 캐시에서 참조 된 개체를 유지하면 가비지 수집이 캐시에 도달하지 못합니다. 그것은 바뀌 었습니다 : 먼저 캐시에서 참조를 제거한 다음 오브젝트가 가비지 수집됩니다. – Humberto
[가비지 콜렉션 알림] (http://msdn.microsoft.com/en-us/library/cc713687.aspx)에 대한 MSDN의 기사가 유용 할 수 있습니다. –
@Humberto 실제로 캐시의 객체에 GUID를 보유하고 있습니다. – B3ret