2013-02-05 10 views
22

MemoryCache.AddOrGetExisting के व्यवहार के रूप में वर्णित किया गया है:मेमोरी कैश। AddOrGetExisting क्या है?

निर्दिष्ट कुंजी और एक मूल्य और एक पूर्ण समाप्ति मूल्य का उपयोग कर कैश में एक कैश प्रविष्टि जोड़ता है।

और यह देता है कि: एक ही कुंजी के साथ एक कैश प्रविष्टि मौजूद

हैं, तो मौजूदा कैश प्रविष्टि; अन्यथा, शून्य।

इन अर्थशास्त्र के साथ एक विधि का उद्देश्य क्या है? इसका एक उदाहरण क्या है?

+2

आलसी http://stackoverflow.com/a/15894928/1575281 –

+3

के साथ संयुक्त उपयोग का एक उदाहरण अच्छा है मुझे खुशी है कि मैं अकेला नहीं हूं ... मैं उस मूल्य को प्राप्त करने की उम्मीद कर रहा था जिसे मैंने अभी पारित किया था पहली कॉल पर वापस, –

उत्तर

18

ऐसी स्थितियां होती हैं जहां आप केवल एक कैश प्रविष्टि बनाना चाहते हैं यदि कोई मिलान प्रविष्टि पहले से मौजूद नहीं है (यानी, आप मौजूदा मान को ओवरराइट नहीं करना चाहते हैं)।

AddOrGetExisting आपको यह परमाणु रूप से करने की अनुमति देता है। AddOrGetExisting के बिना एक परमाणु, थ्रेड-सुरक्षित तरीके से गेट-टेस्ट-सेट करना असंभव होगा। उदाहरण के लिए:

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 पर भी विकिपीडिया प्रविष्टियों सक्षम बनाता है।)

+0

अच्छा स्पष्टीकरण। लेकिन हम फिर 'एड' का उपयोग क्यों करेंगे? क्या हमेशा 'AddOrGetExisting' का उपयोग करना बेहतर नहीं है? – Joze

+2

यह सख्ती से "असंभव" नहीं होगा, क्योंकि आप लॉक स्टेटमेंट के भीतर गेट/सेट कॉल को लपेट सकते हैं। – rymdsmurf

4

मैंने वास्तव में इसका उपयोग नहीं किया है, लेकिन मुझे लगता है कि एक संभावित उपयोग केस यह है कि यदि आप बिना किसी विशेष कुंजी के लिए नई प्रविष्टि के साथ कैश को बिना शर्त अद्यतन करना चाहते हैं और आप स्पष्ट रूप से पुरानी प्रविष्टि को वापस लेना चाहते हैं।

+0

+1 "जब आप पुराने प्रविष्टि को स्पष्ट रूप से निपटाना चाहते हैं" – Seph

+2

यह समझ में आता है, लेकिन मुझे आश्चर्य है कि यह सच है ... कोई भी यह समझाता नहीं है कि यह पहली बार क्यों शून्य हो जाता है आप 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 की नहीं निपटाने के लिए पारित कहते हैं। यह समस्याग्रस्त हो सकता है यदि आप कस्टम परिवर्तन मॉनीटर का उपयोग करते हैं जो महंगे संसाधन ट्रैकिंग तंत्र सेट करते हैं। आम तौर पर, जब कैश प्रविष्टि को निकाल दिया जाता है, तो कैश सिस्टम आपके चेंज मॉनिटर पर Dipose() पर कॉल करता है। यह आपको घटनाओं को अनियंत्रित करने का मौका देता है। जब AddOrGetExisting एक मौजूदा प्रविष्टि देता है, हालांकि, आपको इसका ख्याल रखना होगा।

+0

इसके बारे में भी जागरूक होना: 'जोड़ें' विधियों या हुड के तहत 'AddOrGetExisting' को कॉल करना। – springy76

संबंधित मुद्दे