मुझे लगता है कि इस कोड में समसामयिक मुद्दे हैं:
const string CacheKey = "CacheKey";
static string GetCachedData()
{
string expensiveString =null;
if (MemoryCache.Default.Contains(CacheKey))
{
expensiveString = MemoryCache.Default[CacheKey] as string;
}
else
{
CacheItemPolicy cip = new CacheItemPolicy()
{
AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddMinutes(20))
};
expensiveString = SomeHeavyAndExpensiveCalculation();
MemoryCache.Default.Set(CacheKey, expensiveString, cip);
}
return expensiveString;
}
समसामयिक मुद्दे का कारण यह है कि कई थ्रेड्स एक शून्य कुंजी प्राप्त कर सकते हैं और फिर कैश में डेटा डालने का प्रयास कर सकते हैं।
इस कोड को संगति प्रमाण बनाने के लिए सबसे छोटा और साफ तरीका क्या होगा? मैं अपने कैश संबंधित कोड में एक अच्छे पैटर्न का पालन करना पसंद करता हूं। एक ऑनलाइन लेख के लिए एक लिंक एक बड़ी मदद होगी।
अपडेट करें:
मैं @Scott चेम्बरलेन के उत्तर के आधार पर इस कोड के साथ आया था। किसी को भी इस के साथ किसी भी प्रदर्शन या संगरोध मुद्दा मिल सकता है? यदि यह काम करता है, तो यह कोड और त्रुटियों की कई पंक्ति को बचाएगा।
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Caching;
namespace CachePoc
{
class Program
{
static object everoneUseThisLockObject4CacheXYZ = new object();
const string CacheXYZ = "CacheXYZ";
static object everoneUseThisLockObject4CacheABC = new object();
const string CacheABC = "CacheABC";
static void Main(string[] args)
{
string xyzData = MemoryCacheHelper.GetCachedData<string>(CacheXYZ, everoneUseThisLockObject4CacheXYZ, 20, SomeHeavyAndExpensiveXYZCalculation);
string abcData = MemoryCacheHelper.GetCachedData<string>(CacheABC, everoneUseThisLockObject4CacheXYZ, 20, SomeHeavyAndExpensiveXYZCalculation);
}
private static string SomeHeavyAndExpensiveXYZCalculation() {return "Expensive";}
private static string SomeHeavyAndExpensiveABCCalculation() {return "Expensive";}
public static class MemoryCacheHelper
{
public static T GetCachedData<T>(string cacheKey, object cacheLock, int cacheTimePolicyMinutes, Func<T> GetData)
where T : class
{
//Returns null if the string does not exist, prevents a race condition where the cache invalidates between the contains check and the retreival.
T cachedData = MemoryCache.Default.Get(cacheKey, null) as T;
if (cachedData != null)
{
return cachedData;
}
lock (cacheLock)
{
//Check to see if anyone wrote to the cache while we where waiting our turn to write the new value.
cachedData = MemoryCache.Default.Get(cacheKey, null) as T;
if (cachedData != null)
{
return cachedData;
}
//The value still did not exist so we now write it in to the cache.
CacheItemPolicy cip = new CacheItemPolicy()
{
AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddMinutes(cacheTimePolicyMinutes))
};
cachedData = GetData();
MemoryCache.Default.Set(cacheKey, cachedData, cip);
return cachedData;
}
}
}
}
}
Dictionary<string, object>
जहां कुंजी आपके द्वारा उपयोग की जाने वाली एक ही कुंजी है MemoryCache
और शब्दकोश में ऑब्जेक्ट सिर्फ एक बुनियादी है Object
जिसे आप लॉक करते हैं। हालाँकि, यह कहा जा रहा है, मैं आपको जॉन हन्ना के उत्तर के माध्यम से पढ़ता हूं। उचित प्रोफाइलिंग के बिना, आप लेट के दो उदाहरणों को SomeHeavyAndExpensiveCalculation()
चलाने के बजाय लॉकिंग के साथ अपने कार्यक्रम को धीमा कर सकते हैं और एक परिणाम निकाल दिया जाता है।
ReaderWriterLockSlim
?