2013-02-05 36 views
22

描述的MemoryCache.AddOrGetExisting的行为:什么是MemoryCache.AddOrGetExisting for?

添加使用指定的关键字和一个值 和绝对过期值的高速缓存条目到缓存中。

并且它返回:

如果使用相同的密钥缓存条目存在,现有的缓存项;否则为空。

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

+2

一个使用结合懒惰的例子http://stackoverflow.com/a/15894928/1575281 –

+3

嗯,我很高兴我不是唯一一个......我期待得到我刚刚通过的价值回到第一个电话,非空 –

回答

18

通常情况下,如果匹配条目尚不存在(即,您不想覆盖现有值),则只需创建缓存条目。

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-setcompare-and-swap维基百科条目。)

+0

很好的解释。但是,为什么我们只用'添加'呢?总是使用AddOrGetExisting是不是更好? – Joze

+2

这不会是严格“不可能”的,因为你可以将Get/Set调用包装在一个锁定语句中。 – rymdsmurf

4

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

+0

+1为“当你想明确处置旧条目” – Seph

+2

这是有道理的,但我不知道是否是真的......似乎没有人解释为什么它第一次返回null你调用AddOrGetExisting。 –

4

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返回现有条目时,您必须亲自处理。

+0

也要注意:在引擎盖下添加'方法或调用'AddOrGetExisting'。 – springy76