Для начала позвольте мне просто выбросить туда, что я знаю, что код ниже не является потокобезопасным (исправление: может быть). То, с чем я борюсь, - это найти реализацию, которая есть, и то, что я действительно могу пройти с ошибкой. Я сейчас реорганизую большой проект WCF, который требует некоторых (в основном) статических данных, кэшированных и заполненных из базы данных SQL. Он должен истекать и «обновляться» не реже одного раза в день, поэтому я использую MemoryCache.Безопасность памяти MemoryCache, требуется ли блокировка?
Я знаю, что приведенный ниже код не должен быть потокобезопасным, но я не могу заставить его терпеть неудачу при большой нагрузке и усложнять ситуацию, когда поиск в Google показывает реализации в обоих направлениях (с и без блокировок в сочетании с дебатами независимо от того, нужны они или нет) .
Может ли кто-либо, кто знает MemoryCache в многопоточной среде, дать мне окончательное представление о необходимости блокировки в случае необходимости, чтобы вызов для удаления (который редко будет вызван, но его требование) не будет выбрасывать во время извлечение/репопуляция.
public class MemoryCacheService : IMemoryCacheService
{
private const string PunctuationMapCacheKey = "punctuationMaps";
private static readonly ObjectCache Cache;
private readonly IAdoNet _adoNet;
static MemoryCacheService()
{
Cache = MemoryCache.Default;
}
public MemoryCacheService(IAdoNet adoNet)
{
_adoNet = adoNet;
}
public void ClearPunctuationMaps()
{
Cache.Remove(PunctuationMapCacheKey);
}
public IEnumerable GetPunctuationMaps()
{
if (Cache.Contains(PunctuationMapCacheKey))
{
return (IEnumerable) Cache.Get(PunctuationMapCacheKey);
}
var punctuationMaps = GetPunctuationMappings();
if (punctuationMaps == null)
{
throw new ApplicationException("Unable to retrieve punctuation mappings from the database.");
}
if (punctuationMaps.Cast<IPunctuationMapDto>().Any(p => p.UntaggedValue == null || p.TaggedValue == null))
{
throw new ApplicationException("Null values detected in Untagged or Tagged punctuation mappings.");
}
// Store data in the cache
var cacheItemPolicy = new CacheItemPolicy
{
AbsoluteExpiration = DateTime.Now.AddDays(1.0)
};
Cache.AddOrGetExisting(PunctuationMapCacheKey, punctuationMaps, cacheItemPolicy);
return punctuationMaps;
}
//Go oldschool ADO.NET to break the dependency on the entity framework and need to inject the database handler to populate cache
private IEnumerable GetPunctuationMappings()
{
var table = _adoNet.ExecuteSelectCommand("SELECT [id], [TaggedValue],[UntaggedValue] FROM [dbo].[PunctuationMapper]", CommandType.Text);
if (table != null && table.Rows.Count != 0)
{
return AutoMapper.Mapper.DynamicMap<IDataReader, IEnumerable<PunctuationMapDto>>(table.CreateDataReader());
}
return null;
}
}
ObjectCache является поточно, Я не думаю, что ваш класс может потерпеть неудачу. http://msdn.microsoft.com/en-us/library/system.runtime.caching.objectcache(v=vs.110).aspx Возможно, вы одновременно отправляетесь в базу данных, но это будет использовать только больше CPU чем это необходимо. –
Хотя ObjectCache является потокобезопасным, его реализация может и не быть. Таким образом, вопрос MemoryCache. – Haney