2016-05-27 11 views
0

Ich aktualisiere das Wörterbuch mit einer Methode, die eine Liste aufnimmt. Diese Liste enthält, was die aktualisierten Werte sein sollten, die im Wörterbuch gespeichert sind. Zum Beispiel: Ich habe die Werte 1,2,3,4 in meinem Wörterbuch gespeichert. Ein Thread versucht, die Werte im Wörterbuch anhand der Liste 0, 1, 3, 5 zu aktualisieren. Meine "refresh" -Methode in diesem Thread muss 2,4 aus dem Wörterbuch entfernen und 0,5 hinzufügen.C# Thread sicher "Aktualisieren" Inhalt eines ConcurrentDictionary

Ich habe mehrere Threads, die versuchen, diese "Aktualisierung" in schneller Folge zu tun, also möchte ich sicherstellen, dass ihre Operationen nicht überlappen und das Wörterbuch durcheinander bringen. Aus diesem Grund brauche ich jeden Thread, der versucht, das Wörterbuch zu aktualisieren, um seine Operationen abzuschließen, bevor ich zum nächsten Thread übergehe. Ich muss auch sicherstellen, dass das Wörterbuch in der Reihenfolge aktualisiert wird, in der die Threads versuchen, es zu aktualisieren.

In meinem aktuellen Code erstellt ein Thread eine neue Liste und ruft Refresh() auf, um das Wörterbuch im SubscriptionCache zu aktualisieren. Ich habe jeden Thread für eine Zeit zwischen 3-8 ms schlafen vor dem Erstellen einer neuen Liste, dann Aktualisieren des Wörterbuchs mit der neuen Liste.

Hier ist ein Blick auf mein Code:

public static class SubscriptionCache 
    { 
     private static ConcurrentDictionary<int, Subscription> _firstPartySubscriptionIds = new ConcurrentDictionary<int, Subscription>(); 

     //This compares the contents of the dictionary and new list, 
     then updates the dictionary accordingly. 
     internal static void Refresh(IEnumerable<Subscription> firstPartySubscriptionIds) 
     { 
      lock(_firstPartySubscriptionIds) 
      { 
      try 
      { 
       Compare(firstPartySubscriptionIds, true).ForEach((s) => 
       { 
        var t = _firstPartySubscriptionIds.TryAdd(s.GetHashCode(), s); Print("Added" + s.SystemID + " Success: " + t + " With Key: " + s.GetHashCode()); 
       }); 

       Compare(firstPartySubscriptionIds, false).ForEach((s) => 
       { 
        var t = _firstPartySubscriptionIds.TryRemove(s.GetHashCode(), out s); Print("Removed" + s.SystemID + "Success: " + t + " With key: " + s.GetHashCode()); 
       }); 


       LastRefreshedOn = DateTime.Now; 
      } 
      catch { } 
      } 
     } 

     private static List<Subscription> Compare(IEnumerable<Subscription> firstPartySubscriptionIds, bool reverse) 
     { 
      var masterList = _firstPartySubscriptionIds.Values.ToList(); 
      var newList = firstPartySubscriptionIds.ToList(); 
      var returnList = new List<Subscription>(); 

      if (reverse == false) // Returns elements in the old list which are NOT in the new list 
      { 
       foreach (Subscription s in masterList) 
       { 
        if (!newList.Contains(s)) 
        { 
         returnList.Add(s); 
        } 
       } 
      } 
      else //Returns elements in the new list which are NOT in the old list 
      { 
       foreach (Subscription s in newList) 
       { 
        if (!masterList.Contains(s)) 
        { 
         returnList.Add(s); 
        } 
       } 
      } 
      return returnList; 
     } 
+1

Sind Sie sicher, dass das einfache Sperren für Sie zu Performance-Problemen führt? – Evk

+0

Sie müssen Ihren Code überprüfen. – progpow

+0

@Evk Jetzt, da ich darüber nachdenke, sehe ich nicht, wie mein Programm ohne es funktionieren könnte. Ich kann mir keinen anderen Weg vorstellen, wie dies konzeptionell funktionieren könnte. –

Antwort

1

ConcurrentDictionary nicht nur magisch alles machen mit Beteiligung mehrerer Threads arbeiten. Es macht nur alle Methoden der Struktur logisch atomar. Wenn Sie mehrere Operationen als eine atomare Operation ausführen möchten, die Sie anscheinend ausführen möchten, müssen Sie Ihre Threads explizit dafür verwalten (z. B. durch Sperren).