MemoryCache.AddOrGetExisting 有啥用?

Posted

技术标签:

【中文标题】MemoryCache.AddOrGetExisting 有啥用?【英文标题】:What is MemoryCache.AddOrGetExisting for?MemoryCache.AddOrGetExisting 有什么用? 【发布时间】:2013-01-19 19:56:11 【问题描述】:

MemoryCache.AddOrGetExisting的行为描述为:

使用指定的键和值将缓存条目添加到缓存中 和绝对到期值。

它会返回:

如果存在具有相同key的缓存条目,则现有缓存条目;否则为空。

具有这些语义的方法的目的是什么?有什么例子吗?

【问题讨论】:

结合懒惰***.com/a/15894928/1575281的使用示例 我很高兴我不是唯一一个......我希望在第一次调用时得到我刚刚传入的值,而不是 null 【参考方案1】:

在某些情况下,您只想在不存在匹配条目的情况下创建缓存条目(也就是说,您不想覆盖现有值)。

AddOrGetExisting 允许您以原子方式执行此操作。如果没有AddOrGetExisting,就不可能以原子的、线程安全的方式执行get-test-set。例如:

 Thread 1                         Thread 2
 --------                         --------

 // check whether there's an existing entry for "foo"
 // the call returns null because there's no match
 Get("foo")

                                  // check whether there's an existing entry for "foo"
                                  // the call returns null because there's no match
                                  Get("foo")

 // set value for key "foo"
 // assumes, rightly, that there's no existing entry
 Set("foo", "first thread rulez")

                                  // set value for key "foo"
                                  // assumes, wrongly, that there's no existing entry
                                  // overwrites the value just set by thread 1
                                  Set("foo", "second thread rulez")

(另请参阅Interlocked.CompareExchange 方法,它可以在变量级别实现更复杂的等效项,以及test-and-set 和compare-and-swap 上的***条目。)

【讨论】:

很好的解释。但是为什么我们只使用Add呢?总是使用AddOrGetExisting不是更好吗? 严格来说这不是“不可能的”,因为您可以将 Get/Set 调用包装在 lock 语句中。【参考方案2】:

LukeH 的回答是正确的。因为其他答案表明该方法的语义可能会有不同的解释,所以我认为值得指出的是,AddOrGetExisting 实际上不会更新现有的缓存条目。

所以这段代码

Console.WriteLine(MemoryCache.Default.AddOrGetExisting("test", "one", new CacheItemPolicy()) ?? "(null)"); Console.WriteLine(MemoryCache.Default.AddOrGetExisting("test", "two", new CacheItemPolicy())); Console.WriteLine(MemoryCache.Default.AddOrGetExisting("test", "three", new CacheItemPolicy()));

将打印

(空值) 一 一

另一件需要注意的事情:当AddOrGetExisting 找到一个现有的缓存条目时,它不会处理传递给调用的 CachePolicy。如果您使用设置昂贵的资源跟踪机制的自定义更改监视器,这可能会出现问题。通常,当缓存条目被驱逐时,缓存系统会在 ChangeMonitors 上调用Dipose()。这使您有机会取消注册事件等。但是,当AddOrGetExisting 返回现有条目时,您必须自己处理。

【讨论】:

还要注意:Add 方法或在后台调用 AddOrGetExisting【参考方案3】:

我实际上并没有使用过这个,但我想一个可能的用例是,如果您想用特定键的新条目无条件地更新缓存,并且您想显式处理返回的旧条目。

【讨论】:

+1 表示“当您想明确处理旧条目时” 这是有道理的,但我想知道这是不是真的......似乎没有人解释为什么它在您第一次调用 AddOrGetExisting 时返回 null。 有意义的是它第一次返回 null - 从名称来看,它不存在所以它添加 - 否则返回。然后,您还可以使用它来检查该值是否已经存在。 你已经有了现有的值,你正在传递它!除了方便之外,您为什么需要在返回类型中使用它。是的,这太令人惊讶了,但是有旧值的有效用例。

以上是关于MemoryCache.AddOrGetExisting 有啥用?的主要内容,如果未能解决你的问题,请参考以下文章