MVC 5 HttpContext.Current.Cache метод завершается ошибкой при одновременном попадании в 2 потока
Я использую следующий сервисный метод для кеширования результата запроса:
private readonly CoreDbContext _dbContext;
public EcommerceProductService()
{
_dbContext = GetDbContext();
}
public IEnumerable<EcommerceProduct> GetAllCached()
{
var cachedResult = HttpContext.Current.Cache["EcommerceProductService.GetAllCached"] as IEnumerable<EcommerceProduct>;
if (cachedResult == null)
{
var result = _dbContext.EcommerceProducts.ToList();
HttpContext.Current.Cache.Insert("EcommerceProductService.GetAllCached", result);
return result;
}
return cachedResult;
}
На определенной странице этот метод вызывается одновременно двумя потоками (потому что мне нужно отобразить всю коллекцию товаров дважды, но с разными фильтрами).
Как ни странно, при первом запуске приложения только один из потоков "выигрывает" и получает список продуктов, а другой получает ноль. Если я обновлю страницу, они оба начнут работать нормально (потому что в этот момент они извлекают результат из кэша), но в первый раз, когда это только один или другой, они никогда не работают оба.
Я также попытался обернуть весь код в оператор Lock, но это ничего не изменило. Что мне не хватает?
private readonly CoreDbContext _dbContext;
private static readonly object Locker = new object();
public EcommerceProductService()
{
_dbContext = GetDbContext();
}
public IEnumerable<EcommerceProduct> GetAllCached()
{
lock (Locker)
{
var cachedResult = HttpContext.Current.Cache["EcommerceProductService.GetAllCached"] as IEnumerable<EcommerceProduct>;
if (cachedResult == null)
{
var result = _dbContext.EcommerceProducts.ToList();
HttpContext.Current.Cache.Insert("EcommerceProductService.GetAllCached", result);
return result;
}
return cachedResult;
}
}
1 ответ
Измени свой _locker
декларация
private static object _locker = new object();
Как у вас сейчас, каждый экземпляр EcommerceProductService
присваивает ему новое значение, делая блокировку бесполезной.