更改ASP.NET缓存项目到期的频率?

时间:2008-11-06 12:18:05

标签: asp.net caching

我注意到ASP.NET缓存项每20秒检查一次(并且可能被删除)(每次HH时奇怪的是:MM:00,HH:MM:20和HH:MM:40)。我花了大约15分钟来查看如何更改此参数而没有任何成功。我还尝试在web.config中设置以下内容,但它没有帮助:

<cache privateBytesPollTime="00:00:05" />

我不是想做任何疯狂的事情,但如果它是5秒而不是20秒,或者至少为10,我会很高兴。

4 个答案:

答案 0 :(得分:19)

使用Reflector进行探测,发现间隔是硬编码的。到期由内部CacheExpires类处理,其静态构造函数包含

_tsPerBucket = new TimeSpan(0, 0, 20);

_tsPerBucketreadonly,因此以后无法修改任何配置设置。

然后在CacheExpires.EnableExpirationTimer() ...

中设置将触发检查过期项目的计时器
DateTime utcNow = DateTime.UtcNow;
TimeSpan span = _tsPerBucket - new TimeSpan(utcNow.Ticks % _tsPerBucket.Ticks);
this._timer = new Timer(new TimerCallback(this.TimerCallback), null,
    span.Ticks / 0x2710L, _tsPerBucket.Ticks / 0x2710L);

span的计算可确保计时器正好在:00,:20,:40秒时触发,但我看不出有任何理由要打扰。计时器调用的方法是internal,所以我认为没有办法设置自己的计时器来更频繁地调用它(忽略反射)。

然而,好消息是你不应该有任何理由关心间隔。 Cache.Get()检查项目是否已过期,如果有,则立即从缓存中删除该项目并返回null。因此,即使过期的项目可能会在缓存中保留最多20秒,您也永远不会从缓存中获取过期项目。

答案 1 :(得分:2)

根据documentation,privateBytesPollTime用于“工作进程内存使用”,默认值为1秒。我不认为这与缓存项目删除有关。

我确实使用项目删除回调确认了您的结果 - 看起来项目在分钟的底部被移除,:20和40秒。这表明一个项目可能会在缓存中保留最多20秒,超过在它们上设置的AbsoluteExpiration。我找不到任何文件说明是否可以更改20秒的轮询间隔。

答案 2 :(得分:2)

疯狂但有效的解决方案(需要所有步骤):

// New value for cache expiration cycle
// System.Web.Caching.CacheExpires._tsPerBucket;
// Set 1 seconds instead of 20sec
const string assembly = "System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
var type = Type.GetType("System.Web.Caching.CacheExpires, " + assembly, true, true);
var field = type.GetField("_tsPerBucket", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, TimeSpan.FromSeconds(1));

// Recreate cache
// HttpRuntime._theRuntime._cacheInternal = null;
// HttpRuntime._theRuntime._cachePublic = null;
type = typeof (HttpRuntime);
field = type.GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic);
var runtime = field.GetValue(null);
field = type.GetField("_cachePublic", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(runtime, null);
field = type.GetField("_cacheInternal", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(runtime, null);

答案 3 :(得分:0)

对于它的价值,您可以查看question I have asked:我附上了一个示例代码,证明尽管我设置了10秒的absolute expiration time,但每次都会发生更新回调40秒。