在asp.net中锁定缓存的最佳方法是什么?

时间:2020-03-05 18:46:20  来源:igfitidea点击:

我知道在某些情况下,例如长时间运行的进程,锁定ASP.NET缓存很重要,这样可以避免其他用户对该资源的后续请求再次执行该长时间进程而不是访问缓存。

cto在ASP.NET中实现缓存锁定的最佳方法是什么?

解决方案

回答

Craig Shoemaker在asp.net缓存上表现出色:
http://polymorphicpodcast.com/shows/webperformance/

回答

CodeGuru的本文介绍了各种缓存锁定方案以及ASP.NET缓存锁定的一些最佳做法:

在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

}

回答

我看到了一个最近被称为正确状态袋访问模式的模式,它似乎与此有关。

我对其进行了一些修改,使其具有线程安全性。

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

回答

为了完整起见,完整的示例如下所示。

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