当您将项目添加到System.Web.Caching.Cache具有绝对到期日期时,如下例所示,Asp.Net如何表现?可以:
只需将项目标记为已过期,然后执行CacheItemRemovedCallback下一次访问尝试?
从缓存中删除该项并CacheItemRemovedCallback立即执行?
HttpRuntime.Cache.Insert(key,
new object(),
null,
DateTime.Now.AddSeconds(seconds),
Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable,
OnCacheRemove);
Run Code Online (Sandbox Code Playgroud)MSDN似乎表明它立即发生.例如,"ASP.NET缓存概述"的"过期"部分说"ASP.NET在过期时会自动从缓存中删除项目".类似地,主题"如何:从缓存中删除项时通知应用程序"主题中的示例说"如果在调用GetReport[示例中的方法] 之间超过15秒,ASP.NET将从中删除报告缓存".
尽管如此,这些都不是明确的.他们没有说"回调是立即执行的",我可以设想他们的作者可能认为上面的选项1算作"删除"一个项目.所以我做了一个快速而肮脏的测试,而且,它似乎立即执行 - 即使没有人访问我的网站,我也会定期进行第六十二次回调.
尽管如此,我的测试很快而且很脏,并且在我的回答评论中是否有办法在.Net Web应用程序中每天运行一个进程而无需编写Windows服务或SQL服务器作业,有人建议使用Asp.Net实际上是推迟删除和执行回调,直到某些东西再次尝试访问缓存.
任何人都可以权威地解决这个问题,还是仅仅考虑实施细节?
Jef*_*nal 38
Hurray for Reflector!
实际上删除了过期的缓存项(并且在调用回调时):
1)某些东西试图访问缓存项.
2)该ExpiresBucket.FlushExpiredItems方法运行并到达项目.此方法是硬编码的,每20秒执行一次(StackOverflow问题的接受答案)ASP.NET缓存项目到期的更改频率证实我通过Reflector读取了此代码.但是,这需要额外的资格(阅读).
Asp.Net为服务器上的每个CPU维护一个缓存(我不确定它们是否代表逻辑或物理CPU); 这些中的每一个都维护一个CacheExpires实例,该实例具有每20秒Timer调用其FlushExpiredItems方法的对应实例.
此方法按顺序迭代缓存过期数据(ExpiresBucket实例数组)的另一个"桶"集合,FlushExpiredItems依次调用每个桶的方法.
此方法(ExpiresBucket.FlushExpiredItems)首先迭代存储桶中的所有缓存项,如果项目已过期,则将其标记为已过期.然后(我在这里大大简化)它迭代它标记为已过期的项目并删除它们,执行CacheItemRemovedCallback(实际上,它调用CacheSingle.Remove,调用CacheInternal.DoRemove,然后CacheSingle.UpdateCache,然后CacheEntry.Close,实际上调用回调).
所有这些都是串行发生的,所以有可能会阻塞整个进程并保持状态(并将缓存项的到期时间从指定的到期时间推回).
然而,在这个时间分辨率下,最小的到期间隔为20秒,可能阻塞很长时间的过程的唯一部分是执行CacheItemRemovedCallbacks.其中任何一个都可以无限制地阻止给定Timer的FlushExpiredItems线程.(虽然二十秒后,它Timer会产生另一个FlushExpiredItems线程.)
总而言之,Asp.Net不保证它会在指定时间执行回调,但在某些情况下会这样做.只要到期时间间隔超过20秒,并且只要缓存不必执行耗时CacheItemRemovedCallbacks(全局 - 任何回调都可能会干扰其他任何回调),它就可以按计划执行到期回调.这对某些应用来说已经足够了,但对其他应用来说却不尽如人意.
| 归档时间: |
|
| 查看次数: |
8597 次 |
| 最近记录: |