/// <summary> /// Gets an item from cache or calls the callback method and stores the result in the cache /// </summary> /// <typeparam name="T">The return type</typeparam> /// <param name="key">The key of the item in the cache</param> /// <param name="getItemDelegate">Delegate callback to get the item if needed</param> /// <param name="duration">The duration in seconds to store the item in the cache</param> /// <returns>The cached item or result of the callback if item is not in the cache</returns> public T Get <T>(string key, Func <T> getItemDelegate, int duration) where T : class { lock (SyncObject) { var cache = GetCache(); var item = cache.Get(key) as T; if (item != null) { return(item); } item = getItemDelegate(); cache.Add(key, item, DateTime.Now.AddSeconds(duration)); if (!RetainCacheDurationDetail) { return(item); } var cacheDetail = new CacheItemDetail { AddedOn = DateTime.Now, Duration = duration }; cache.Add($"{key}{CacheKeyDurationSuffix}", cacheDetail, DateTime.Now.AddSeconds(duration)); return(item); } }
private async Task <T> RunFactory <T, TParam>(ObjectCache cache, string key, Func <TParam, Task <T> > getItemFactory, TParam inputParam, int duration) where T : class { await PurgeOldLocks(); var cacheLock = Locks.GetOrAdd(key, k => new SemaphoreSlim(1)); try { //Wait for anyone currently running the factory. await cacheLock.WaitAsync(); //Check to see if another factory has already ran while we waited. var oldResult = (T)cache.Get(key); if (oldResult != null) { return(oldResult); } //Run the factory then cache the result. var newResult = await getItemFactory(inputParam); cache.Add(key, newResult, DateTime.Now.AddSeconds(duration)); if (!RetainCacheDurationDetail) { return(newResult); } var cacheDetail = new CacheItemDetail { AddedOn = DateTime.Now, Duration = duration }; cache.Add($"{key}{CacheKeyDurationSuffix}", cacheDetail, DateTime.Now.AddSeconds(duration)); return(newResult); } finally { cacheLock.Release(); } }