MemoryCache.AddOrGetExisting的行为描述为:
使用指定的键和值将缓存条目添加到缓存中 和绝对到期值。
它返回:
如果存在具有相同密钥的缓存条目,则存在现有缓存条目;否则,null。
使用这些语义的方法的目的是什么?这是一个什么样的例子?
答案 0 :(得分:22)
如果匹配的条目尚不存在(也就是说,您不想覆盖现有值),通常情况下您只想创建缓存条目。
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上的维基百科条目。)
答案 1 :(得分:8)
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()));
将打印
(null) one one
需要注意的另一件事是:当AddOrGetExisting
找到现有的缓存条目时,它将不处理传递给调用的CachePolicy。如果您使用自定义更改监视器来设置昂贵的资源跟踪机制,则可能会出现问题。通常,当驱逐缓存条目时,缓存系统会在您的ChangeMonitors上调用Dipose()
。这使您有机会取消注册事件等。但是,当AddOrGetExisting
返回现有条目时,您必须自己处理。
答案 2 :(得分:4)
我实际上并没有使用过这个,但我想一个可能的用例是,如果你想用一个特定键的新条目无条件地更新缓存,你想要显式处理返回的旧条目。