2009-04-16 17 views
20

In der Vergangenheit habe ich eine Sperre für den Zugriff auf den HttpRuntime.Cache-Mechanismus gesetzt. Ich bin mir nicht sicher, ob ich das Problem in der Vergangenheit wirklich recherchiert habe und es blind mit einem Schloss umgeben habe.HttpRuntime.Cache Best Practices

Denken Sie, dass das wirklich notwendig ist?

+0

http://stackoverflow.com/questions/447705/locking-httpruntime-cache-for-lazy-loading scheint, dass der Cache Thread sicher ist –

+0

Sprache/Plattform? – Javier

Antwort

2

Ich glaube nicht, dass es notwendig ist, den Zugriff auf die HttpRuntime.Cache-Eigenschaft mit einer Sperre zu umbrechen, da die .Cache-Eigenschaft statisch und auch Thread-sicher ist.

Es gibt viele verschiedene Möglichkeiten, auf das Cache-Objekt zuzugreifen (HttpRuntime.Cache, HttpContext.Current.Cache, Page.Cache usw.). Sie alle greifen auf das gleiche Cache-Objekt zu, da es nur ein Cache-Objekt pro Anwendungsdomäne gibt, da es sich tatsächlich um ein thread-sicheres Singleton-Objekt handelt.

10

Dieser Artikel legt nahe, eine Sperre verwendet werden soll:

http://msdn.microsoft.com/en-us/magazine/cc500561.aspx

Zitat:

Das Problem ist, dass wenn Sie eine Abfrage haben, die mit 30 Sekunden dauert und du bist Ausführen der Seite jede Sekunde, in die Zeit, die es dauert, um die Cache-Element zu füllen, 29 andere Anfragen werden kommen, die alle versuchen werden zu Füllen Sie das Cache-Element mit eigenen Abfragen an die Datenbank. Um dieses Problem zu lösen, können Sie eine Threadsperre zu hinzufügen, um die anderen Seitenausführungen von zu stoppen, die die Daten von der Datenbank anfordern.

Hier ist ihr Code-Schnipsel:

// check for cached results 
object cachedResults = ctx.Cache["PersonList"]; 
ArrayList results = new ArrayList(); 

if (cachedResults == null) 
{ 
    // lock this section of the code 
    // while we populate the list 
    lock(lockObject) 
    { 
    cachedResults = ctx.Cache["PersonList"]; 
    // only populate if list was not populated by 
    // another thread while this thread was waiting 
    if (cachedResults == null) 
    { 
     cachedResults = ... 
     ctx.Cache["PersonList"] = cachedResults; 
    } 
    } 
} 

ich diesen Code nicht getestet, aber ich wäre sehr interessiert, jemanden zu hören, der diesen Ansatz in einer Produktionsumgebung ausgewertet hat.

+11

Ich denke nicht, dass dies in Bezug auf die Caching-Thread-Sicherheit erforderlich ist - es ist mehr zu verhindern, dass mehrere Zugriffe auf die Datenbank eine potenziell teure Abfrage ausführen. – zcrar70

+1

Ich stimme dir zu. – frankadelic

+5

Nur ein kleiner, aber wichtiger Fehler im Beispiel: zwischen der Sperre (lockObject) und dem if (cachedResults == null) sollte das zwischengespeicherte Element erneut abgerufen werden. Siehe http: // stackoverflow.com/questions/39112/Was ist der beste Weg zum Lock-Cache-in-ASP-net für ein richtiges Beispiel. –

2

Ich denke nicht, Sperren ist die Antwort auf das Problem, insbesondere in der Produktionsumgebung, wo Sie mehrere Server haben Ihre Anwendung ausgeführt.

Das Problem ist, dass, wenn Sie eine Abfrage haben, die 30 Sekunden dauert und Sie die Seite jede Sekunde ausführen, in der Zeit, die es dauert, um das Cache-Element zu füllen, 29 andere Anfragen kommen, die alle wird versuchen, das Cache-Element mit eigenen Abfragen an die Datenbank zu füllen. Um dieses Problem zu lösen, können Sie eine Threadsperre hinzufügen, um zu verhindern, dass die anderen Seitenausführungen die Daten von der Datenbank anfordern.