ما هي أفضل طريقة قفل ذاكرة التخزين المؤقت في asp.net?

StackOverflow https://stackoverflow.com/questions/39112

  •  09-06-2019
  •  | 
  •  

سؤال

أنا أعرف في ظل ظروف معينة ، مثل تشغيل طويلة العمليات ، من المهم قفل ASP.NET ذاكرة التخزين المؤقت من أجل تجنب الطلبات اللاحقة من قبل مستخدم آخر لهذا المورد من تنفيذ عملية طويلة مرة أخرى بدلا من ضرب ذاكرة التخزين المؤقت.

ما هي أفضل طريقة في c# لتنفيذ ذاكرة التخزين المؤقت في قفل ASP.NET?

هل كانت مفيدة؟

المحلول

هنا هو النمط الأساسي:

  • تحقق من ذاكرة التخزين المؤقت عن قيمة المقابل إذا كان متوفر
  • إذا لم تكن القيمة في ذاكرة التخزين المؤقت ، ثم تطبيق القفل
  • داخل القفل ، تحقق من ذاكرة التخزين المؤقت مرة أخرى ، قد تم حظره
  • أداء قيمة ابحث و ذاكرة التخزين المؤقت
  • الإفراج قفل

في التعليمات البرمجية ، يبدو مثل هذا:

private static object ThisLock = new object();

public string GetFoo()
{

  // try to pull from cache here

  lock (ThisLock)
  {
    // cache was empty before we got the lock, check again inside the lock

    // cache is still empty, so retreive the value here

    // store the value in the cache here
  }

  // return the cached value here

}

نصائح أخرى

عن اكتمال كامل سبيل المثال ننظر بشيء من هذا القبيل.

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;

فقط أن أكرر ما بافل وقال: أعتقد أن هذا هو أكثر موضوع طريقة آمنة الكتابة

private T GetOrAddToCache<T>(string cacheKey, GenericObjectParamsDelegate<T> creator, params object[] creatorArgs) where T : class, new()
    {
        T returnValue = HttpContext.Current.Cache[cacheKey] as T;
        if (returnValue == null)
        {
            lock (this)
            {
                returnValue = HttpContext.Current.Cache[cacheKey] as T;
                if (returnValue == null)
                {
                    returnValue = creator(creatorArgs);
                    if (returnValue == null)
                    {
                        throw new Exception("Attempt to cache a null reference");
                    }
                    HttpContext.Current.Cache.Add(
                        cacheKey,
                        returnValue,
                        null,
                        System.Web.Caching.Cache.NoAbsoluteExpiration,
                        System.Web.Caching.Cache.NoSlidingExpiration,
                        CacheItemPriority.Normal,
                        null);
                }
            }
        }

        return returnValue;
    }

هناك حاجة إلى تأمين كل ذاكرة التخزين المؤقت سبيل المثال, بدلا من ذلك نحن بحاجة فقط إلى قفل الرئيسية المحددة التي يتم إدخال أجل.أولا-هاء.لا تحتاج إلى منع الوصول إلى المرحاض الإناث أثناء استخدام المرحاض الذكور :)

تنفيذ أدناه يسمح تأمين محددة ذاكرة التخزين المؤقت-مفاتيح باستخدام المتزامنة القاموس.بهذه الطريقة يمكنك تشغيل GetOrAdd() عن اثنين من مفاتيح مختلفة في نفس الوقت - ولكن ليس على نفس المفتاح في نفس الوقت.

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;
    }
}

كريغ الإسكافي قد قدم عرض ممتاز على asp.net التخزين المؤقت:http://polymorphicpodcast.com/shows/webperformance/

وقد تأتي مع طريقة تمديد التالية:

private static readonly object _lock = new object();

public static TResult GetOrAdd<TResult>(this Cache cache, string key, Func<TResult> action, int duration = 300) {
    TResult result;
    var data = cache[key]; // Can't cast using as operator as TResult may be an int or bool

    if (data == null) {
        lock (_lock) {
            data = cache[key];

            if (data == null) {
                result = action();

                if (result == null)
                    return result;

                if (duration > 0)
                    cache.Insert(key, result, null, DateTime.UtcNow.AddSeconds(duration), TimeSpan.Zero);
            } else
                result = (TResult)data;
        }
    } else
        result = (TResult)data;

    return result;
}

لقد استخدمت كل @جون أوين @user378380 إجابات.الحل يسمح لك لتخزين الباحث و منطقي القيم داخل ذاكرة التخزين المؤقت aswell.

يرجى تصحيح لي إذا كان هناك أي أخطاء أو ما إذا كان يمكن أن تكون مكتوبة على نحو أفضل قليلا.

رأيت نمط واحد دعا مؤخرا الصحيحة الدولة حقيبة نمط الوصول ، والذي يبدو أن أتطرق إلى هذا.

انا عدلت عليه قليلا إلى أن مؤشر الترابط-الآمن.

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;
}

هذا المقال من CodeGuru يفسر مختلف ذاكرة التخزين المؤقت تأمين سيناريوهات وكذلك بعض أفضل الممارسات ASP.NET ذاكرة التخزين المؤقت تأمين:

مزامنة ذاكرة التخزين المؤقت الوصول في ASP.NET

لقد كتب المكتبة أن يحل هذه المسألة بالذات: الصخور.التخزين المؤقت

أيضا لقد كتبت عن هذه المشكلة في التفاصيل و شرح السبب في أنه من المهم هنا.

أنا تعديل @user378380 رمز لمزيد من المرونة.بدلا من العودة TResult الآن إرجاع كائن على قبول أنواع مختلفة في النظام.أيضا إضافة بعض المعلمات من المرونة.كل فكرة ينتمي إلى @user378380.

 private static readonly object _lock = new object();


//If getOnly is true, only get existing cache value, not updating it. If cache value is null then      set it first as running action method. So could return old value or action result value.
//If getOnly is false, update the old value with action result. If cache value is null then      set it first as running action method. So always return action result value.
//With oldValueReturned boolean we can cast returning object(if it is not null) appropriate type on main code.


 public static object GetOrAdd<TResult>(this Cache cache, string key, Func<TResult> action,
    DateTime absoluteExpireTime, TimeSpan slidingExpireTime, bool getOnly, out bool oldValueReturned)
{
    object result;
    var data = cache[key]; 

    if (data == null)
    {
        lock (_lock)
        {
            data = cache[key];

            if (data == null)
            {
                oldValueReturned = false;
                result = action();

                if (result == null)
                {                       
                    return result;
                }

                cache.Insert(key, result, null, absoluteExpireTime, slidingExpireTime);
            }
            else
            {
                if (getOnly)
                {
                    oldValueReturned = true;
                    result = data;
                }
                else
                {
                    oldValueReturned = false;
                    result = action();
                    if (result == null)
                    {                            
                        return result;
                    }

                    cache.Insert(key, result, null, absoluteExpireTime, slidingExpireTime);
                }
            }
        }
    }
    else
    {
        if(getOnly)
        {
            oldValueReturned = true;
            result = data;
        }
        else
        {
            oldValueReturned = false;
            result = action();
            if (result == null)
            {
                return result;
            }

            cache.Insert(key, result, null, absoluteExpireTime, slidingExpireTime);
        }            
    }

    return result;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top