gpt4 book ai didi

c# - MemoryCache AbsoluteExpiration 行为奇怪

转载 作者:IT王子 更新时间:2023-10-29 04:08:02 24 4
gpt4 key购买 nike

我正在尝试在 .net 4.5 中使用 MemoryCache 来跟踪并自动更新各种项目,但似乎无论我将什么设置为 AbsoluteExpiration 它总是只会在 15 秒或更长时间后过期。

我希望缓存项每 5 秒过期一次,但它总是至少在 15 秒后过期,如果我将过期时间移出,它最终会变成大约 15 秒 + 我的刷新间隔,但绝不会少于超过 15 秒。

是否有一些我没有看到的内部定时器分辨率?我查看了一些反射(reflect)的 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;
}

最佳答案

我想通了。 System.Runtime.Caching.CacheExpires 上有一个名为 _tsPerBucket 的 internal static readonly TimeSpan,它在 20 秒时被硬编码。

显然,此字段用于运行并检查缓存项是否过期的内部计时器。

我正在解决这个问题,方法是使用反射覆盖值并清除默认 MemoryCache 实例以重置所有内容。它似乎有效,即使它是一个巨大的 hack。

这是更新后的代码:

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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com