public async Task CacheExpirationTimeTest() { const int cacheSeconds = 2; var testObject = new TestObject() { Name = "My Test" }; var weakReference = new TimedCacheWeakReference <TestObject>(testObject, TimeSpan.FromSeconds(cacheSeconds)); Assert.IsTrue(weakReference.StrongReferenceAvailable, "No strong reference available"); //Drop my strong refrence, and perform a GC testObject = null; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); //We are well within our cache time, so we should still have a reference Assert.IsTrue(weakReference.StrongReferenceAvailable, "Lost reference before cache timeout expired"); //Now wait past our cache second time, then do a GC and verify we've lost the reference await Task.Delay(TimeSpan.FromSeconds(cacheSeconds + 1)); GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); Assert.IsFalse(weakReference.StrongReferenceAvailable, "Strong reference is still available after cache expiration"); }
private static void RegisterExpiration(TimedCacheWeakReference <T> classToRegister, T target) { lock (cacheExpirationLock) { //Force set the target while we are within this class, in case it was cleared out in our expiration handler while we were waiting for the lock classToRegister.strongReference = target; var existing = registeredCacheExpirationItems.FirstOrDefault(item => item.TimedCacheWeakReference == classToRegister); if (target == null) { //Strong reference has already been claimed, so remove this item from the collection registeredCacheExpirationItems.Remove(existing); } else { if (existing == null) { //Register a new item for expiration registeredCacheExpirationItems.Add(new CacheExpirationRecord() { ExpirationTime = DateTime.Now.Add(classToRegister.CacheDuration), TimedCacheWeakReference = classToRegister }); } else { //Extend expiration lease existing.ExpirationTime = DateTime.Now.Add(classToRegister.CacheDuration); } //Initialize our timer if it isn't already running if (cacheExpirationTimer == null) { cacheExpirationTimer = new Timer(OnCacheExpirationTimer_Elapsed, null, cacheTimerInterval, cacheTimerInterval); } } } }