20

我想使用 System.Runtime.Caching.MemoryCache 来缓存我的一些对象。我想确保该对象每天刷新一次(绝对过期),但如果它在最后一小时内没有使用,我也想让它过期(滑动过期)。我尝试这样做:

object item = "someitem";
var cache = MemoryCache.Default;
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now.AddDays(1);
policy.SlidingExpiration = TimeSpan.FromHours(1);
cache.Add("somekey", item, policy);

但是我得到了一个“ArgumentException”,其中“AbsoluteExpiration 必须是 DateTimeOffset.MaxValue 或 SlidingExpiration 必须是 TimeSpan.Zero”。

4

5 回答 5

10

您可以使用 CacheEntryChangeMonitor 实现这两种方案的缓存过期。插入一个没有绝对过期信息的缓存项,然后使用该项创建一个空的 monitorChange 并将其与第二个缓存项链接,您实际上将在其中保存一个slidingTimeOut 信息。

        object data = new object();
        string key = "UniqueIDOfDataObject";
        //Insert empty cache item with absolute timeout
        string[] absKey = { "Absolute" + key };
        MemoryCache.Default.Add("Absolute" + key, new object(), DateTimeOffset.Now.AddMinutes(10));

        //Create a CacheEntryChangeMonitor link to absolute timeout cache item
        CacheEntryChangeMonitor monitor = MemoryCache.Default.CreateCacheEntryChangeMonitor(absKey);

        //Insert data cache item with sliding timeout using changeMonitors
        CacheItemPolicy itemPolicy = new CacheItemPolicy();
        itemPolicy.ChangeMonitors.Add(monitor);
        itemPolicy.SlidingExpiration = new TimeSpan(0, 60, 0);
        MemoryCache.Default.Add(key, data, itemPolicy, null);
于 2013-05-15T19:22:02.640 回答
5

使用 ILSpy 快速反映调用时显示此代码MemoryCache.Add

if (policy.AbsoluteExpiration != ObjectCache.InfiniteAbsoluteExpiration && policy.SlidingExpiration != ObjectCache.NoSlidingExpiration)
    {
        throw new ArgumentException(R.Invalid_expiration_combination, "policy");
    }

因此,本机不支持 Absolute 和 Sliding Expiration 的这种组合。

您应该将自己转向自定义实现。

于 2013-05-13T14:47:09.377 回答
2

You have two options:

  1. Inherit from MemoryCache or it's parent ObjectCache and implement your own caching mechanism.
  2. Implement a ChangeMonitor which may be more difficult (see Note to Inheritors)
于 2013-05-13T15:17:36.963 回答
2

dieguitofernandez 答案的一些附加说明(顺便说一句,这是一个非常好的解决方案):

ChangeMonitor 不会在达到 AbsoluteExpiration 的确切时刻触发,因为不是每秒都检查 Expiration。通知第二个缓存项可能需要几秒钟。将 1 天作为 AbsoluteExpiration 没关系,但是如果您需要两个到期时间都是准确的(就像我所做的那样),您必须首先使用密钥和绝对密钥。

if (cache.Contains("Absolute" + key) && cache.Contains(key))

这样,两个过期时间都会立即检查,您可以确定该项目没有过期。

(我可以将此作为评论发布,因为我是新来的,对不起!)

于 2013-09-11T10:09:13.737 回答
-2

DateTime.Now.AddDays(1)不返回 DateTimeOffset,而是返回 DateTime ( AddDays() )。

所以这很可能是一个无效的论点。

因此,请尝试DateTimeOffset.Now.AddDays(1)DateTimeOffset)。

于 2013-05-13T14:45:05.887 回答