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 присваивает ему новое значение, делая блокировку бесполезной.

Другие вопросы по тегам