2016-05-21 6 views
0

Ich verwende die folgende Service-Methode, um das Ergebnis einer Abfrage cachen:MVC 5 HttpContext.Current.Cache Methode schlägt fehl, wenn du von zwei Threads zur gleichen Zeit getroffen

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; 
    } 

In einer bestimmten Seite , diese Methode wird gleichzeitig von 2 Threads aufgerufen (weil ich die gesamte Sammlung von Produkten zweimal, aber mit verschiedenen Filtern anzeigen muss).

Seltsam, beim ersten Start der Anwendung nur einer der Threads "gewinnt" und erhält die Liste der Produkte, während der andere Null empfängt. Wenn ich die Seite aktualisiere, beginnen beide gut zu funktionieren (weil sie zu diesem Zeitpunkt das Ergebnis aus dem Cache holen), aber das erste Mal, wenn es das eine oder das andere Mal ist, funktionieren beide nie.

Ich habe auch versucht, den gesamten Code in eine Lock-Anweisung zu wickeln, aber es hat nichts geändert. Was vermisse ich?

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; 
     } 

    } 

Antwort

0

auf Ihre _locker Erklärung ändern

private static object _locker = new object(); 

Wie Sie es jetzt haben, weist jede Instanz EcommerceProductService einen neuen Wert zu, wodurch nutzlos sperren.

+0

Wie Sie aus meinem Code sehen können, habe ich genau das getan. Der Konstruktor initialisiert den Wert für new object(). – tocqueville

+0

Das ist das Problem. In jeder neuen Instanz ändern Sie den Wert des statischen Objekts. Entfernen Sie den gesamten Code aus dem Konstruktor. Lasse nur die Deklaration wie ich sie habe. – kagelos

+0

Fertig, aber das Problem bleibt bestehen. Sehe meine aktualisierte Frage. Vielleicht ist das Schloss überhaupt nicht die Antwort. Das Problem könnte woanders sein. – tocqueville

Verwandte Themen