9 Stimmen

Sperre für den Schlüssel eines Dictionary<string, object> verwenden

Ich habe eine Dictionary<string, someobject> .

EDIT: Ich wurde darauf aufmerksam gemacht, dass mein Beispiel schlecht war. Meine Absicht war es nicht, die Referenzen in einer Schleife zu aktualisieren, sondern verschiedene Werte zu aktualisieren, je nachdem, welche Threads die Daten aktualisieren/abrufen müssen. Ich habe die Schleife in eine Methode geändert.

Ich brauche, um Elemente in meinem Wörterbuch zu aktualisieren - ein Schlüssel zu einer Zeit, und ich wunderte mich, wenn es irgendwelche Probleme bei der Verwendung der Sperre auf den Wert .key meines Dictionary-Objekts gibt?

private static Dictionary<string, MatrixElement> matrixElements = new Dictionary<string, MatrixElement>();

//Pseudo-code

public static void UpdateValue(string key)
{
    KeyValuePair<string, MatrixElement> keyValuePair = matrixElements[key];
    lock (keyValuePair.Key)
    {
        keyValuePair.Value  = SomeMeanMethod();
    }
}

Würde das vor Gericht Bestand haben oder scheitern? Ich möchte nur, dass jeder Wert im Wörterbuch unabhängig gesperrt wird, so dass das Sperren (und Aktualisieren) eines Wertes die anderen nicht sperrt. Auch ich bin mir bewusst, die Sperre wird für eine lange Zeit halten - aber die Daten werden ungültig sein, bis vollständig aktualisiert.

0 Stimmen

Keine Antwort, aber Sie wissen, dass Sie, wenn Sie das Paar bereits haben, pair.Value verwenden können, anstatt operator[] erneut im Dictionary aufzurufen?

0 Stimmen

Ich habe es versucht, aber der Wert ist schreibgeschützt, so hat es mir meine IDE gesagt.

0 Stimmen

Sie können die foreach-Elemente nicht ändern

0voto

Ray Hayes Punkte 14625

In Ihrem Beispiel können Sie nicht tun, was Sie tun wollen!

Sie erhalten eine System.InvalidOperationException mit einer Botschaft von Sammlung wurde geändert; Aufzählungsoperation darf nicht ausgeführt werden.

Hier ist ein Beispiel zum Beweis:

using System.Collections.Generic;
using System;

public class Test
{
    private Int32 age = 42;

    static public void Main()
    {
       (new Test()).TestMethod();
    }

    public void TestMethod()
    {
        Dictionary<Int32, string> myDict = new Dictionary<Int32, string>();

        myDict[age] = age.ToString();

        foreach(KeyValuePair<Int32, string> pair in myDict)
        {
            Console.WriteLine("{0} : {1}", pair.Key, pair.Value);
            ++age;
            Console.WriteLine("{0} : {1}", pair.Key, pair.Value);
            myDict[pair.Key] = "new";
            Console.WriteLine("Changed!");
        }
    }   
}

Die Ausgabe würde lauten:

42 : 42
42 : 42

Unhandled Exception: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()
   at Test.TestMethod()
   at Test.Main()

0 Stimmen

Ich möchte nicht das gesamte Wörterbuch sperren, sondern nur den Schlüsselpaarwert, damit nicht zwei Prozesse gleichzeitig denselben Wert im Schlüsselpaarwert aktualisieren.

0 Stimmen

Ich ändere nicht den Schlüssel, sondern nur den Wert, also sollte es kein Problem sein.

0voto

babackman Punkte 133

Ich sehe da ein paar mögliche Probleme:

  1. Strings können gemeinsam genutzt werden, so dass Sie nicht unbedingt wissen, wer sonst noch aus welchem Grund auf dieses Schlüsselobjekt zugreift.
  2. Strings könnten pas gemeinsam genutzt werden: Sie können auf einen String-Schlüssel mit dem Wert "Key1" sperren und ein anderes Stück Code kann ein anderes String-Objekt haben, das ebenfalls die Zeichen "Key1" enthält. Für das Wörterbuch ist es derselbe Schlüssel, aber was das Sperren betrifft, sind es unterschiedliche Objekte.
  3. Diese Sperre verhindert keine Änderungen an den Wertobjekten selbst, d. h. matrixElements[someKey].ChangeAllYourContents()

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X