我们正在使用虚拟路径提供程序从文件系统中检索特定扩展的项目。基本实现确实返回以下
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);
答案 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;
}
}