什么是MemoryCache.AddOrGetExisting?

Dav*_*ier 24 .net c# memorycache

MemoryCache.AddOrGetExisting的行为描述为:

使用指定的键以及值和绝对到期值将高速缓存条目添加到高速缓存中.

它返回:

如果存在具有相同密钥的高速缓存条目,则存在现有高速缓存条目; 否则,null.

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

Luk*_*keH 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")
Run Code Online (Sandbox Code Playgroud)

(另请参阅该Interlocked.CompareExchange方法,该方法在变量级别启用更复杂的等效项,以及测试和设置以及比较和交换的维基百科条目.)

  • 它不会严格"不可能",因为您可以将Get/Set调用包装在lock语句中. (3认同)

Sve*_*ler 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.如果您使用自定义更改监视器来设置昂贵的资源跟踪机制,则可能会出现问题.通常,当驱逐缓存条目时,缓存系统会调用Dipose()您的ChangeMonitors.这使您有机会取消注册事件等.AddOrGetExisting但是,当返回现有条目时,您必须自己处理.