2012-07-23 9 views
7

Sind die folgenden Annahmen für diesen Code gültig? Ich habe einige Hintergrundinformationen unter den Code gestellt, aber ich denke nicht, dass es relevant ist.Erstellen von dynamischen Sperren zur Laufzeit in ASP.NET

Annahme 1: Da dies eine einzelne Anwendung ist, mache ich die Annahme, dass es von einem einzigen Prozess behandelt wird. Daher werden statische Variablen zwischen Threads geteilt, und das statische Deklarieren meiner Sammlung von Sperrobjekten ist gültig.

Annahme 2: Wenn ich weiß, dass der Wert bereits im Wörterbuch ist, muss ich nicht lesen lesen. Ich könnte ein ConcurrentDictionary verwenden, aber ich glaube, dass dieses sicher ist, da ich nicht aufzählen (oder löschen), und der Wert wird existieren und nicht ändern, wenn ich UnlockOnValue() aufrufen.

Annahme 3: Ich kann die Keys-Auflistung sperren, da diese Referenz nicht geändert wird, auch wenn die zugrunde liegende Datenstruktur dies tut.

private static Dictionary<String,Object> LockList = 
    new Dictionary<string,object>(); 

private void LockOnValue(String queryStringValue) 
{ 
    lock(LockList.Keys) 
    { 
     if(!LockList.Keys.Contains(queryStringValue)) 
     { 
      LockList.Add(screenName,new Object()); 
     } 
     System.Threading.Monitor.Enter(LockList[queryStringValue]); 
    } 
} 

private void UnlockOnValue(String queryStringValue) 
{ 
    System.Threading.Monitor.Exit(LockList[queryStringValue]); 
} 

Dann würde ich diesen Code wie verwenden:

LockOnValue(Request.QueryString["foo"]) 
//Check cache expiry 
//if expired 
    //Load new values and cache them. 
//else 
    //Load cached values 
UnlockOnValue(Request.QueryString["foo"]) 

Hintergrund: ich eine App in ASP.NET mich zu erwecken, dass die Download-Daten basierend auf einer einzigen benutzerdefinierten Variablen in der Abfrage Zeichenfolge. Die Anzahl der Werte wird sehr begrenzt sein. Ich muss die Ergebnisse für jeden Wert für einen bestimmten Zeitraum zwischenspeichern.

Ansatz: entschied ich mich lokale Dateien zu verwenden, um die Daten zu zwischenzuspeichern, die nicht die beste Option ist, aber ich wollte es versuchen, da dies nicht kritisch ist und die Leistung ist kein großes Problem. Ich benutzte 2 Dateien pro Option, eine mit dem Cache-Ablaufdatum und eine mit den Daten.

Ausgabe: Ich bin nicht sicher, was der beste Weg, Verriegelung zu tun ist, und ich bin nicht allzu vertraut mit Threadingprobleme in .NET (einer der Gründe, warum ich diesen Ansatz gewählt haben). Basierend auf dem, was verfügbar ist, und was ich lese, dachte ich, dass das oben genannte funktionieren sollte, aber ich bin mir nicht sicher und wollte eine zweite Meinung.

+1

Was ist das Problem mit 'HttpRuntime.Cache'? – scottm

+0

Das war meine erste Wahl, aber es hat sich merkwürdig verhalten. Vielleicht liegt es daran, dass meine Seite die Antwort löscht und eine Textdatei zurückgibt, aber ich habe nicht zu tief gegraben, nachdem ich auf ähnliche Probleme gestoßen war, die im gesamten Internet veröffentlicht wurden, ohne Antworten, die für mich funktionierten. Die einzige Sache, auf die ich nicht eingegangen bin, war die IIS-Konfiguration und ob Caching korrekt konfiguriert wurde. Ich mache das vielleicht später noch, aber es ist so unkritischer Code und das warf Fragen auf, auf die ich Antworten wollte, auch wenn es nicht die beste Architektur ist. – Kendrick

+0

Ich versuche eine sehr ähnliche Lösung zu implementieren, in der ich Methodenergebnisse zwischenspeichere. Ich brauche auch eine Möglichkeit, verschiedene Cache-Sperren zu erstellen, und ich frage mich, ob Ihre Lösung den Test der Zeit überstanden hat, Prost. –

Antwort

6

Ihre aktuelle Lösung sieht ziemlich gut aus. Die zwei Dinge, die ich ändern würde:

1: UnlockOnValue muss in einem endgültigen Block gehen. Wenn eine Ausnahme ausgelöst wird, wird die Sperre niemals aufgehoben.

2: LockOnValue ist etwas ineffizient, da es zweimal nach einem Wörterbuch sucht.Dies ist keine große Sache für ein kleines Wörterbuch, aber für ein größeres Wörterbuch möchten Sie zu TryGetValue wechseln.

Auch Ihre Annahme 3 gilt - zumindest für jetzt. Der Dictionary-Vertrag garantiert jedoch nicht, dass die Keys-Eigenschaft immer dasselbe Objekt zurückgibt. Und da es so einfach ist, sich nicht darauf zu verlassen, würde ich es eher empfehlen. Immer wenn ich ein Objekt zum Sperren benötige, erstelle ich einfach ein Objekt für diesen Zweck. Etwas wie:

private static Object _lock = new Object(); 
+0

Ich hätte das im Pseudocode angegeben, aber ich habe es im finally-Block. Ich habe nie an TryGetValue gedacht, aber das ist wahrscheinlich eine bessere Option. Das Wörterbuch wird klein sein, aber immer noch gut zum Nachdenken. – Kendrick

+0

Ja, es ist ein ärgerliches Ärgernis von mir, einen Aufruf von Contains zu sehen und dann einen Aufruf an [], da beide das Element finden müssen. – bmm6o

1

lock hat nur einen Bereich eines einzelnen Prozesses. Wenn Sie Prozesse überspannen wollen, müssen Sie Primitive wie Mutex (benannt) verwenden.

lock ist das gleiche wie Monitor.Enter und Monitor.Exit. Wenn Sie auch Monitor.Enter und Monitor.Exit tun, ist es redundant.

Sie müssen nicht lesen, aber Sie müssen die "Transaktion" des Überprüfens, ob der Wert nicht vorhanden ist und es hinzufügen. Wenn Sie diese Anweisungsfolge nicht sperren, kann bei der Suche nach dem Schlüssel und beim Hinzufügen und Hinzufügen eines Schlüssels etwas anderes dazwischenkommen. Dies führt zu einer Ausnahme. Die Sperre, die du machst, ist ausreichend, um das zu tun (du brauchst keine zusätzlichen Aufrufe von Enter und Exit - lock wird das für dich tun).

+0

Ich gehe davon aus, dass alle Threads für diese Anwendung aus demselben Prozess stammen. Die Dokumentation und die Beispiele, die ich mir angesehen habe, deuten darauf hin, obwohl ich mir immer noch nicht 100% sicher bin. Es ist wirklich meine zweite Annahme, über die ich mir nicht ganz sicher bin. Ich denke, die erste ist richtig, und die dritte ist wahrscheinlich richtig, aber es gibt keinen Grund, dies zu tun, nur ein Schloss-Objekt für das Wörterbuch erstellen (dh könnte funktionieren, aber wahrscheinlich schlechten Code) – Kendrick

+0

Wenn es eine Anwendung und alle Threads sind In einer einzigen Instanz des Prozesses passt die Sperre zu dieser Situation. –

Verwandte Themen