我正在尝试使用 MemoryCache 在 .net 4.5 中跟踪并自动更新各种项目,但似乎无论我设置为 AbsoluteExpiration 它总是只会在 15 秒或更长时间后过期。
我希望缓存项每 5 秒过期一次,但它总是在至少 15 秒后过期,如果我将过期时间移出,它最终将是 15 秒 + 我的刷新间隔,但绝不会少于 15 秒.
是否有一些我没有看到的内部计时器分辨率?我看了一点反射出来的 System.Runtime.Caching.MemoryCache 代码,没有什么对我来说很突出,而且我无法在互联网上找到其他有此问题的人。
我在下面有一个非常基本的例子来说明这个问题。
我要的是CacheEntryUpdate 每 5 秒左右被击中一次并更新新数据,但是,正如我所说,它只会在 15 秒以上被击中。
static MemoryCache MemCache;
static int RefreshInterval = 5000;
protected void Page_Load(object sender, EventArgs e)
{
if (MemCache == null)
MemCache = new MemoryCache("MemCache");
if (!MemCache.Contains("cacheItem"))
{
var cacheObj = new object();
var policy = new CacheItemPolicy
{
UpdateCallback = new CacheEntryUpdateCallback(CacheEntryUpdate),
AbsoluteExpiration = DateTimeOffset.UtcNow.AddMilliseconds(RefreshInterval)
};
var cacheItem = new CacheItem("cacheItem", cacheObj);
MemCache.Set("cacheItem", cacheItem, policy);
}
}
private void CacheEntryUpdate(CacheEntryUpdateArguments args)
{
var cacheItem = MemCache.GetCacheItem(args.Key);
var cacheObj = cacheItem.Value;
cacheItem.Value = cacheObj;
args.UpdatedCacheItem = cacheItem;
var policy = new CacheItemPolicy
{
UpdateCallback = new CacheEntryUpdateCallback(CacheEntryUpdate),
AbsoluteExpiration = DateTimeOffset.UtcNow.AddMilliseconds(RefreshInterval)
};
args.UpdatedCacheItemPolicy = policy;
}
Best Answer-推荐答案 strong>
我已经想通了。有一个 internal static readonly TimeSpan 在 System.Runtime.Caching.CacheExpires 上调用 _tsPerBucket,它在 20 秒硬编码。
显然,此字段用于运行并检查缓存项是否已过期的内部计时器。
我正在通过使用反射覆盖值并清除默认 MemoryCache 实例来重置所有内容来解决此问题。它似乎有效,即使它是一个巨大的黑客。
这是更新后的代码:
static MemoryCache MemCache;
static int RefreshInterval = 1000;
protected void Page_Load(object sender, EventArgs e)
{
if (MemCache == null)
{
const string assembly = "System.Runtime.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
var type = Type.GetType("System.Runtime.Caching.CacheExpires, " + assembly, true, true);
var field = type.GetField("_tsPerBucket", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, TimeSpan.FromSeconds(1));
type = typeof(MemoryCache);
field = type.GetField("s_defaultCache", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, null);
MemCache = new MemoryCache("MemCache");
}
if (!MemCache.Contains("cacheItem"))
{
var cacheObj = new object();
var policy = new CacheItemPolicy
{
UpdateCallback = new CacheEntryUpdateCallback(CacheEntryUpdate),
AbsoluteExpiration = DateTimeOffset.UtcNow.AddMilliseconds(RefreshInterval)
};
var cacheItem = new CacheItem("cacheItem", cacheObj);
MemCache.Set("cacheItem", cacheItem, policy);
}
}
private void CacheEntryUpdate(CacheEntryUpdateArguments args)
{
var cacheItem = MemCache.GetCacheItem(args.Key);
var cacheObj = cacheItem.Value;
cacheItem.Value = cacheObj;
args.UpdatedCacheItem = cacheItem;
var policy = new CacheItemPolicy
{
UpdateCallback = new CacheEntryUpdateCallback(CacheEntryUpdate),
AbsoluteExpiration = DateTimeOffset.UtcNow.AddMilliseconds(RefreshInterval)
};
args.UpdatedCacheItemPolicy = policy;
}
关于c# - MemoryCache AbsoluteExpiration 行为奇怪,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/12630168/
|