2016-05-24 11 views
4

Ich stolpere über ein Problem, und ich habe keine Ahnung, was ich falsch mache. Ich habe unzählige verschiedene Dinge ausprobiert, aber aus irgendeinem Grund wird es einfach nicht funktionieren. Meine Hauptschleife:Code iteriert nicht über das gesamte Wörterbuch?

static Dictionary<string, int> dict = new Dictionary<string, int>(); 

public static void IterateOverEachUser() 
{ 
    if (dict.Count > 0) { 
     foreach (KeyValuePair<string, int> item in dict.ToList()) 
     { 
      string userName = item.Key; 
      int amountLeft = item.Value; 
      if(amountLeft == 60) 
      { 
       Log(userName + " started!"); 
      } 
      Log(userName + amountLeft); 
      dict[userName] = dict[userName] - 1; 
      amountLeft = item.Value; 
      if(amountLeft == 0) 
      { 
       Log(userName + " ran out!"); 
      } 
     } 
    } 
} 

public static void AddUser(string User) 
{ 
    if (dict.ContainsKey(User)) 
    { 
     Log("User already exists."); 
    } 
    else 
    { 
     dict.Add(User,60); 
     Log("User has been added."); 
    } 
} 

Ich schleife IterateOverEachUser() alle 5 Sekunden. Wenn ich einen Benutzer mit der Methode hinzufüge, ist alles in Ordnung, aber wenn ich einen zweiten hinzufüge, bleibt sein Wert bei 60 hängen, während der andere weiterläuft.

Weiß jemand, warum das passiert? Ich komme aus Java mit HashMaps und mit dem gleichen Code funktioniert es wie beabsichtigt. (Das heißt: Jeder Benutzer wird iteriert, der Wert aller Benutzer wird um 1 abgezogen und dann gestoppt, bis die IterateOverEachUser() -Methode von der 5-Sekunden-Schleife erneut aufgerufen wird).

Vielen Dank im Voraus!

+4

I downvoted bekommen, aber ich bekomme keine konstruktive Kritik? Soweit es mich betrifft, sollte mein Code perfekt funktionieren, oder? Ich postete meinen eigenen Code, ich zeigte umfangreiche Recherchen, ich erklärte mein Problem und erkläre, was ich von dem Code erwarte. Dies verdient keinen Downvote .. imo –

+2

seien Sie vorsichtig, Sie ändern ein Wörterbuch während Sie es durchlaufen. In den meisten Sprachen kann dies ein Problem sein –

+0

@ HoàngLong Vielen Dank für Ihr Feedback! Ich habe auch darüber nachgedacht, aber das Hinzufügen von ".ToList()" löst das Problem leider nicht. Würdest du auch einen besseren Weg finden, um das Wörterbuch während des Laufs zu bearbeiten? –

Antwort

4

amountLeft = item.Value; wird falsche Werte erzeugen (der alte).

Auch wenn Sie mit Timern und statischen Ressourcen arbeiten, ist es besser, Ihre Methode Thread-Safe mit lock zu machen.

Der Code unten Test funktioniert perfekt für mich:

static Dictionary<string, int> dict = new Dictionary<string, int>(); 
static object lockObject = new Object(); 

public static void IterateOverEachUser() 
{ 
    lock (lockObject) 
    { 
     if (dict.Count > 0) 
     { 
      foreach (KeyValuePair<string, int> item in dict.ToList()) 
      { 
       string userName = item.Key; 
       int amountLeft = item.Value; 
       if (amountLeft == 60) 
       { 
        Console.WriteLine(userName + " started!"); 
       } 
       Console.WriteLine(userName + amountLeft); 
       dict[userName] = dict[userName] - 1; 
       amountLeft = dict[userName]; 
       if (amountLeft == 0) 
       { 
        Console.WriteLine(userName + " ran out!"); 
       } 

       Console.WriteLine("User " + item.Key + " = " + amountLeft); 
      } 
     } 
    } 
} 

public static void AddUser(string User) 
{ 
    if (dict.ContainsKey(User)) 
    { 
     Console.WriteLine("User already exists."); 
    } 
    else 
    { 
     dict.Add(User, 60); 
     Console.WriteLine("User has been added."); 
    } 
} 

static void Main(string[] args) 
{ 

    AddUser("U1"); 
    AddUser("U2"); 

    int counter = 1; 
    System.Timers.Timer t1 = new System.Timers.Timer(); 
    t1.Interval = 5000; 
    t1.Elapsed += (oo, ee) => 
    { 
     IterateOverEachUser(); 

     if (counter++ == 5) 
      AddUser("U3"); 
    }; 

    t1.Start(); 

    Console.ReadKey(); 
} 

Ausgang:

User has been added. 
User has been added. 
U1 started! 
U160 
User U1 = 59 
U2 started! 
U260 
User U2 = 59 
U159 
User U1 = 58 
U259 
User U2 = 58 
U158 
User U1 = 57 
U258 
User U2 = 57 
U157 
User U1 = 56 
U257 
User U2 = 56 
U156 
User U1 = 55 
U256 
User U2 = 55 
User has been added. 
U155 
User U1 = 54 
U255 
User U2 = 54 
U3 started! 
U360 
User U3 = 59 
U154 
User U1 = 53 
U254 
User U2 = 53 
U359 
User U3 = 58 
U153 
User U1 = 52 
U253 
User U2 = 52 
U358 
User U3 = 57 
// and so one 
+0

Das Sperren des Objekts funktionierte perfekt! Ich denke, ich muss wieder in die Dokumentation eintauchen und mehr über Threading erfahren. Vielen Dank für Ihre Antwort und danke an alle anderen, die auch dazu beigetragen haben! –

Verwandte Themen