的MemoryCache AbsoluteExpiration举止怪异 [英] MemoryCache AbsoluteExpiration acting strange

查看:501
本文介绍了的MemoryCache AbsoluteExpiration举止怪异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用的MemoryCache 在.NET 4.5跟踪和自动更新的各种项目,但似乎无论什么我设置为 AbsoluteExpiration 它会永远只能在15秒以上到期。



我要缓存项目每5秒后到期,但它总是到期后至少15秒,如果我移动的到期时间了,它最终会被像15秒+我的刷新间隔,但从来没有超过15秒的时间。



有没有办法,我没有看到一些内部定时器的分辨率?我通过一点点看着反射 System.Runtime.Caching.MemoryCache 代码并没有什么站出来给我,我一直没能找到任何人谁拥有这在互联网上发布了。



下面我有一个非常简单的例子说明了这个问题。



我要的是 CacheEntryUpdate 每5秒左右,用新的数据更新被打,但正如我已经说过了,它永远只能被命中15+秒。

 静态的MemoryCache内存缓存; 
静态INT RefreshInterval = 5000;

保护无效的Page_Load(对象发件人,EventArgs五)
{
如果(MEMCACHE == NULL)
MEMCACHE =新的MemoryCache(内存缓存);

如果(MemCache.Contains(cacheItem)!)
{
变种cacheObj =新的对象();
VAR政策=新CacheItemPolicy
{
UpdateCallback =新CacheEntryUpdateCallback(CacheEntryUpdate),
AbsoluteExpiration = DateTimeOffset.UtcNow.AddMilliseconds(RefreshInterval)
};
变种cacheItem =新CacheItem(cacheItem,cacheObj);
MemCache.Set(cacheItem,cacheItem,政策);
}
}

私人无效CacheEntryUpdate(CacheEntryUpdateArguments参数)
{
VAR cacheItem = MemCache.GetCacheItem(args.Key);
VAR cacheObj = cacheItem.Value;

cacheItem.Value = cacheObj;
args.UpdatedCacheItem = cacheItem;
VAR政策=新CacheItemPolicy
{
UpdateCallback =新CacheEntryUpdateCallback(CacheEntryUpdate),
AbsoluteExpiration = DateTimeOffset.UtcNow.AddMilliseconds(RefreshInterval)
};
args.UpdatedCacheItemPolicy =政策;
}


解决方案

我已经想通了。这里有一个内部静态只读时间跨度上System.Runtime.Caching.CacheExpires称为_tsPerBucket是在20秒硬编码。



显然,这一领域是什么在运行和检查,看看是否缓存项过期内部定时器使用。



我解决此通过使用反射覆盖值并清除默认的MemoryCache实例重置一切工作正常。它似乎工作,即使它是一个巨大的黑客



下面是更新后的代码:

 静态的MemoryCache内存缓存; 
静态INT RefreshInterval = 1000;

保护无效的Page_Load(对象发件人,EventArgs五)
{
如果(MEMCACHE == NULL)
{
常量字符串总成=系统。 Runtime.Caching,版本= 4.0.0.0,文化=中性公钥= b03f5f7f11d50a3a;
变种类型= Type.GetType(System.Runtime.Caching.CacheExpires,+组装,真实,真实);
VAR字段= type.GetField(_ tsPerBucket,BindingFlags.Static | BindingFlags.NonPublic可);
field.SetValue(空,TimeSpan.FromSeconds(1));

型= ty​​peof运算(的MemoryCache);
场= type.GetField(s_defaultCache,BindingFlags.Static | BindingFlags.NonPublic可);
field.SetValue(NULL,NULL);

MEMCACHE =新的MemoryCache(内存缓存);
}

如果(MemCache.Contains(cacheItem)!)
{
变种cacheObj =新的对象();
VAR政策=新CacheItemPolicy
{
UpdateCallback =新CacheEntryUpdateCallback(CacheEntryUpdate),
AbsoluteExpiration = DateTimeOffset.UtcNow.AddMilliseconds(RefreshInterval)
};
变种cacheItem =新CacheItem(cacheItem,cacheObj);
MemCache.Set(cacheItem,cacheItem,政策);
}
}

私人无效CacheEntryUpdate(CacheEntryUpdateArguments参数)
{
VAR cacheItem = MemCache.GetCacheItem(args.Key);
VAR cacheObj = cacheItem.Value;

cacheItem.Value = cacheObj;
args.UpdatedCacheItem = cacheItem;
VAR政策=新CacheItemPolicy
{
UpdateCallback =新CacheEntryUpdateCallback(CacheEntryUpdate),
AbsoluteExpiration = DateTimeOffset.UtcNow.AddMilliseconds(RefreshInterval)
};
args.UpdatedCacheItemPolicy =政策;
}


I'm trying to use a MemoryCache in .net 4.5 to keep track of and automatically update various items, but it seems like no matter what I set as an AbsoluteExpiration it will always only expire in 15 seconds or more.

I want the cache items to expire every 5 seconds, but it always expires in at least 15 seconds, and if I move the expiration time out, it will end up being something like 15 seconds + my refresh interval, but never less than 15 seconds.

Is there some internal timer resolution that I'm not seeing? I looked through a bit of the reflected System.Runtime.Caching.MemoryCache code and nothing stood out to me, and I haven't been able to find anybody else who has this issue out on the internet.

I have a very basic example below that illustrates the problem.

What I want is for CacheEntryUpdate to be hit every 5 seconds or so and update with new data, but, as I've said, it only ever gets hit in 15+ seconds.

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;
}

解决方案

I've figured it out. There's an internal static readonly TimeSpan on System.Runtime.Caching.CacheExpires called _tsPerBucket that is hardcoded at 20 seconds.

Apparently, this field is what's used on the internal timers that run and check to see if cache items are expired.

I'm working around this by overwriting the value using reflection and clearing the default MemoryCache instance to reset everything. It seems to work, even if it is a giant hack.

Here's the updated code:

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;
}

这篇关于的MemoryCache AbsoluteExpiration举止怪异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆