What is the best way to lock cache in asp.net?

前端 未结 10 678
悲&欢浪女
悲&欢浪女 2020-11-27 09:33

I know in certain circumstances, such as long running processes, it is important to lock ASP.NET cache in order to avoid subsequent requests by another user for that resourc

相关标签:
10条回答
  • 2020-11-27 10:16

    There is no need to lock the whole cache instance, rather we only need to lock the specific key that you are inserting for. I.e. No need to block access to the female toilet while you use the male toilet :)

    The implementation below allows for locking of specific cache-keys using a concurrent dictionary. This way you can run GetOrAdd() for two different keys at the same time - but not for the same key at the same time.

    using System;
    using System.Collections.Concurrent;
    using System.Web.Caching;
    
    public static class CacheExtensions
    {
        private static ConcurrentDictionary<string, object> keyLocks = new ConcurrentDictionary<string, object>();
    
        /// <summary>
        /// Get or Add the item to the cache using the given key. Lazily executes the value factory only if/when needed
        /// </summary>
        public static T GetOrAdd<T>(this Cache cache, string key, int durationInSeconds, Func<T> factory)
            where T : class
        {
            // Try and get value from the cache
            var value = cache.Get(key);
            if (value == null)
            {
                // If not yet cached, lock the key value and add to cache
                lock (keyLocks.GetOrAdd(key, new object()))
                {
                    // Try and get from cache again in case it has been added in the meantime
                    value = cache.Get(key);
                    if (value == null && (value = factory()) != null)
                    {
                        // TODO: Some of these parameters could be added to method signature later if required
                        cache.Insert(
                            key: key,
                            value: value,
                            dependencies: null,
                            absoluteExpiration: DateTime.Now.AddSeconds(durationInSeconds),
                            slidingExpiration: Cache.NoSlidingExpiration,
                            priority: CacheItemPriority.Default,
                            onRemoveCallback: null);
                    }
    
                    // Remove temporary key lock
                    keyLocks.TryRemove(key, out object locker);
                }
            }
    
            return value as T;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 10:18

    For completeness a full example would look something like this.

    private static object ThisLock = new object();
    ...
    object dataObject = Cache["globalData"];
    if( dataObject == null )
    {
        lock( ThisLock )
        {
            dataObject = Cache["globalData"];
    
            if( dataObject == null )
            {
                //Get Data from db
                 dataObject = GlobalObj.GetData();
                 Cache["globalData"] = dataObject;
            }
        }
    }
    return dataObject;
    
    0 讨论(0)
  • 2020-11-27 10:18

    I saw one pattern recently called Correct State Bag Access Pattern, which seemed to touch on this.

    I modified it a bit to be thread-safe.

    http://weblogs.asp.net/craigshoemaker/archive/2008/08/28/asp-net-caching-and-performance.aspx

    private static object _listLock = new object();
    
    public List List() {
        string cacheKey = "customers";
        List myList = Cache[cacheKey] as List;
        if(myList == null) {
            lock (_listLock) {
                myList = Cache[cacheKey] as List;
                if (myList == null) {
                    myList = DAL.ListCustomers();
                    Cache.Insert(cacheKey, mList, null, SiteConfig.CacheDuration, TimeSpan.Zero);
                }
            }
        }
        return myList;
    }
    
    0 讨论(0)
  • 2020-11-27 10:18

    This article from CodeGuru explains various cache locking scenarios as well as some best practices for ASP.NET cache locking:

    Synchronizing Cache Access in ASP.NET

    0 讨论(0)
提交回复
热议问题