CacheDependency不会在加载时驱逐缓存(使用虚拟路径提供程序)

时间:2017-06-28 03:13:42

标签: c# asp.net-mvc caching dispose invalidation

我们正在使用虚拟路径提供程序从文件系统中检索特定扩展的项目。基本实现确实返回以下

        if (Handler != null)
        {
            return new MyCacheDependency(virtualPath, virtualPathDependencies, utcStart);
        }
        else
        {
            return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
        }

MyCacheDependency在HttpContext.Current.Cache对象上使用以下Insert,并带有相应的CacheItemRemovedCallback

CacheItemRemovedCallback onCacheItemRemoved = new CacheItemRemovedCallback(this.MyCacheItemRemovedCallbackMethod);
lock (_cache)
                {
                    _cache.Insert(key, value, new CacheDependency(virtualPath), DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Default, onCacheItemRemoved);
                }

我的MyCacheItemRemovedCallbackMethod的实现是

// I did read that this needs to be a static implementation and thread-safe too
 public void MyCacheItemRemovedCallbackMethod(string key, object value, CacheItemRemovedReason reason)
        {   
            this.SetUtcLastModified(DateTime.UtcNow);
            this.Invalidate();
            cacheRemoveReason = reason;

            switch (cacheRemoveReason.ToString())
            {
                case dependencyChanged:
                    {
                        // what should be disposed here?
                        this.CacheDependencyDispose();
                        this.Dispose();
                        break;
                    }
                case expired:
                    {
                        // what should be disposed here?
                        this.CacheDependencyDispose();
                        this.Dispose();
                        break;
                    }
                case removed:
                    {   
                        // what should be disposed here?
                        this.CacheDependencyDispose();
                        this.Dispose();
                        break;
                    }
                default:
                        this.CacheDependencyDispose();
                        this.Dispose();
                        break;
            }
        }

上述工作在大多数环境中都很有魅力,但是当系统负载过重时,缓存不会被正确驱逐。

  

问题

在负载很重的情况下,当在文件系统中更新项目时,会发生这种情况,同时会向资源发送多个请求。我仍然假设正在删除缓存,但我们仍然可以在我们的应用程序中看到旧内容。

我可以看到,因为负载被释放,所以即使在过期之前被移除的用例也会被唤起。我还可以在日志中看到mycallback方法被正确引发,但网页没有带来文件系统的最新内容。

如果正在执行remove以释放内存,则最新的cache.insert甚至无法正确更新缓存。

建议/反馈

  • 我没有在每个中正确处理特定的依赖关系 以上场景?任何反馈都表示赞赏。
  • 我是否遗漏了导致此问题的虚拟路径提供程序中的任何设置?
  • 是否需要应用程序或页面级别设置 启用/禁用?
  • 我遗失的其他任何物品?

更新

My invalidate执行NotifyDependencyChanged

base.NotifyDependencyChanged(this, EventArgs.Empty);

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。基本上,NotifyDependencyChanged具有已添加到依赖项的对象的lastwritetime UTC的值。

在这种情况下,我们不必将this.UtcLastModified显式设置为DateTime.Now。我还注意到CacheItemRemovedCallback仅用于通知(缓存,日志等),不能用于处理依赖项。

谈判其他几个最佳实践,我能够得到以下代码。

public void MyCacheItemRemovedCallbackMethod(string key, object value, CacheItemRemovedReason reason)
        {   
            this.Invalidate();
            cacheRemoveReason = reason;

            switch (cacheRemoveReason.ToString())
            {
                case dependencyChanged:
                    {
                        Log.Debug("I am logging my reason with datetime modified");
                        break;
                    }
                case expired:
                    {
                       Log.Debug("I am logging my reason with datetime modified");
                        break;
                    }
                case removed:
                    {   
                        Log.Debug("I am logging my reason with datetime modified");
                       break;
                    }
                default:
                        Log.Debug("I am logging my reason with datetime modified");
                        break;
            }
        }