Locking pattern for proper use of .NET MemoryCache

前端 未结 9 2110
栀梦
栀梦 2020-11-30 17:13

I assume this code has concurrency issues:

const string CacheKey = \"CacheKey\";
static string GetCachedData()
{
    string expensiveString =null;
    if (Me         


        
9条回答
  •  醉酒成梦
    2020-11-30 17:34

    public interface ILazyCacheProvider : IAppCache
    {
        /// 
        /// Get data loaded - after allways throw cached result (even when data is older then needed) but very fast!
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        T GetOrAddPermanent(string key, Func getData, TimeSpan slidingExpiration);
    }
    
    /// 
    /// Initialize LazyCache in runtime
    /// 
    public class LazzyCacheProvider: CachingService, ILazyCacheProvider
    {
        private readonly Logger _logger = LogManager.GetLogger("MemCashe");
        private readonly Hashtable _hash = new Hashtable();
        private readonly List  _reloader = new List();
        private readonly ConcurrentDictionary _lastLoad = new ConcurrentDictionary();  
    
    
        T ILazyCacheProvider.GetOrAddPermanent(string dataKey, Func getData, TimeSpan slidingExpiration)
        {
            var currentPrincipal = Thread.CurrentPrincipal;
            if (!ObjectCache.Contains(dataKey) && !_hash.Contains(dataKey))
            {
                _hash[dataKey] = null;
                _logger.Debug($"{dataKey} - first start");
                _lastLoad[dataKey] = DateTime.Now;
                _hash[dataKey] = ((object)GetOrAdd(dataKey, getData, slidingExpiration)).CloneObject();
                _lastLoad[dataKey] = DateTime.Now;
               _logger.Debug($"{dataKey} - first");
            }
            else
            {
                if ((!ObjectCache.Contains(dataKey) || _lastLoad[dataKey].AddMinutes(slidingExpiration.Minutes) < DateTime.Now) && _hash[dataKey] != null)
                    Task.Run(() =>
                    {
                        if (_reloader.Contains(dataKey)) return;
                        lock (_reloader)
                        {
                            if (ObjectCache.Contains(dataKey))
                            {
                                if(_lastLoad[dataKey].AddMinutes(slidingExpiration.Minutes) > DateTime.Now)
                                    return;
                                _lastLoad[dataKey] = DateTime.Now;
                                Remove(dataKey);
                            }
                            _reloader.Add(dataKey);
                            Thread.CurrentPrincipal = currentPrincipal;
                            _logger.Debug($"{dataKey} - reload start");
                            _hash[dataKey] = ((object)GetOrAdd(dataKey, getData, slidingExpiration)).CloneObject();
                            _logger.Debug($"{dataKey} - reload");
                            _reloader.Remove(dataKey);
                        }
                    });
            }
            if (_hash[dataKey] != null) return (T) (_hash[dataKey]);
    
            _logger.Debug($"{dataKey} - dummy start");
            var data = GetOrAdd(dataKey, getData, slidingExpiration);
            _logger.Debug($"{dataKey} - dummy");
            return (T)((object)data).CloneObject();
        }
    }
    

提交回复
热议问题