Asp.网络缓存模式

本文关键字:模式 缓存 网络 Asp | 更新日期: 2023-09-27 18:00:37

有很多关于线程安全缓存的文章,这里有一个例子:

private static object _lock =  new object();
public void CacheData()
{
   SPListItemCollection oListItems;
       oListItems = (SPListItemCollection)Cache["ListItemCacheName"];
      if(oListItems == null)
      {
         lock (_lock) 
         {
              // Ensure that the data was not loaded by a concurrent thread 
              // while waiting for lock.
              oListItems = (SPListItemCollection)Cache[“ListItemCacheName”];
              if (oListItems == null)
              {
                   oListItems = DoQueryToReturnItems();
                   Cache.Add("ListItemCacheName", oListItems, ..);
              }
         }
     }
}

但是,此示例取决于对缓存的请求以及对缓存的重建。

我正在寻找一种将请求和重建分离的解决方案。下面是场景。

我有一个web服务,我想监控某些类型的错误。如果发生错误,我会创建一个监视器对象和缓存-它是可更新的,并在更新过程中相应地被锁定。到目前为止一切都很好。

在其他地方,我检查缓存对象的存在及其包含的数据。除了一个特定的场景外,这将直接开箱即用。

如果缓存对象正在更新,比如状态更改,我希望等待并获得最新信息,而不是当前信息,如果返回,则会过期。因此,对于我的获取代码,我需要检查对象当前是否正在创建/更新,如果是,请等待,然后重试。

正如我所指出的,有很多缓存锁定模式的例子,但我似乎找不到一个适用于这种情况的例子。如果有任何关于如何进行这项工作的想法,我们将不胜感激?

Asp.网络缓存模式

您可以使用两个锁来尝试以下代码。setter中的写锁非常简单,可以保护缓存不被多个线程写入。getter使用一个简单的双重检查锁。

现在,技巧在于Refresh()方法,它使用与getter相同的锁。该方法使用锁,并在第一步中从缓存中删除列表。它将触发任何getter在第一次null检查中失败并等待锁定。该方法同时获取项,再次设置缓存并释放锁。当它返回到getter时,它再次读取缓存,现在它包含列表。

public class CacheData
{
    private static object _readLock = new object();
    private static object _writeLock = new object();
    public SPListItemCollection ListItem
    {
        get
        {
            var oListItems = (SPListItemCollection) Cache["ListItemCacheName"];
            if (oListItems == null)
            {
                lock (_readLock)
                {
                    oListItems = (SPListItemCollection)Cache["ListItemCacheName"];
                    if (oListItems == null)
                    {
                        oListItems = DoQueryToReturnItems();
                        Cache.Add("ListItemCacheName", oListItems, ..);
                    }
                }
            }
            return oListItems;
        }
        set
        {
            lock (_writeLock)
            {
                Cache.Add("ListItemCacheName", value, ..);
            }
        }
    }
    public void Refresh()
    {
        lock (_readLock)
        {
            Cache.Remove("ListItemCacheName");
            var oListItems = DoQueryToReturnItems();
            ListItem = oListItems;                
        }
    }
}

如果不需要CacheData实例,可以将方法和属性设置为静态。