2011-01-12 8 views
0

Ich habe ein Wörterbuch der Elemente, die ein Thread aktualisiert. Ich möchte eine Methode haben, um die aktualisierte Liste der Elemente mit einem anderen Thread zu erhalten.Die Liste der Objekte aus der Sammlung wird durch den Thread aktualisiert

wie folgt:

internal List<string> GetListOfEntities() 
    {    
     List<string> listOfEntities = new List<string>(); 
     foreach (string entityName in ModelFacade._totalListOfStkObjects.Keys) 
     { 
      listOfEntities.Add(entityName); 
     } 
     return listOfEntities; 
    } 

ModelFacade._totalListOfStkObjects ist die Sammlung von dem Thread aktualisiert. Ich bekomme weiterhin die Ausnahme: "Sammlung wurde geändert; Aufzählungsoperation wird möglicherweise nicht ausgeführt."; Ich habe versucht, _totalListOfStkObjects in eine lokale Sammlung zu kopieren und über das in GetListOfEntities() zu wiederholen .. aber ich bekomme den gleichen Fehler ..?

Irgendwelche Hilfe?

WulfgarPro

+0

Müssen Sie unbedingt mit zwei Threads auf das Wörterbuch zugreifen? Wenn nicht, gibt es Alternativen, wie ein Erzeuger/Verbraucher-Muster. – Jacob

+0

Ein Thread fragt eine externe Anwendung ab, um die Sammlung zu füllen - der andere Thread aktualisiert eine ListBox mit den Elementen. Irgendwelche Beispiele für das Hersteller/Verbraucher-Setup? – wulfgarpro

+0

@WulfgarPro Scheint wie das Hersteller/Verbraucher-Muster ist der Weg zu gehen. –

Antwort

2

Es ist kein garantierter Thread-sichere Art und Weise sein würde, das Wörterbuch zuzugreifen. Ihre beste Wette ist entweder Ihren Code zu ändern, so dass Sie nicht die Sammlung zu teilen oder um das Wörterbuch zu sperren, wenn Zugriff auf:

object dictLock = new object(); 

internal List<string> GetListOfEntities() 
{    
    lock (dictLock) 
    { 
     return ModelFacade._totalListOfStkObjects.Keys.ToList(); 
    } 
} 

Stellen Sie sicher, auch das Wörterbuch sperren, wenn es in einem anderen Thread zu modifizieren.

2

Ändern Sie Ihre Dictionary zu ConcurrentDictionary, wenn Sie .NET verwenden 4. Hier ist ein einfaches Beispiel, um Ihre Frage zu simulieren und zu lösen.

class DataItem 
{ 
    public int Data { get; set; } 
    public bool IsDirty { get; set; } 
} 

var data = new ConcurrentDictionary<string, DataItem>(); 
Thread addingItems = new Thread(() => 
    { 
     for (int i = 0; i < 10000; i++) 
     { 
      data.TryAdd("data " + i, new DataItem { Data = i, IsDirty = true }); 
      Thread.Sleep(100); 
     } 
    }); 
Thread fetchingItems = new Thread(() => 
    { 
     int count = 0; 
     while (count < 100) 
     { 
      foreach (var item in data) 
      { 
       if (item.Value.IsDirty) 
       { 
        Console.WriteLine(item.Key + " " + item.Value); 
        item.Value.IsDirty = false; 
        count++; 
       } 
      } 
     } 
    }); 
addingItems.Start(); 
fetchingItems.Start(); 
0

Sie können das Wörterbuch in eine threadsichere Singleton-Klasse einbinden. Dies sollte die gesamte Funktionalität von ConcurrentDictionary für Dictionary bereitstellen. Die Bezugnahme auf das Wörterbuch sollte nur eine zusätzliche Indirektionsebene erfordern.

Referenz:

Singleton.Instance.myDictionary.Add(1, "Hello World"); 

Erklärung:

public sealed class Singleton 
{ 
    private static volatile Singleton instance; 
    private static object syncRoot = new Object(); 
    public Dictionary<int, string> myDictionary = new Dictionary<int, string>(); 

    private Singleton() {} 

    public static Singleton Instance 
    { 
     get 
     { 
      if (instance == null) 
      { 
       lock (syncRoot) 
       { 
        if (instance == null) 
         instance = new Singleton(); 
       } 
      } 
      return instance; 
     } 
    } 
} 

Blick here für weitere Informationen über die Singleton-Muster in C#. Beachten Sie, dass es nur einen Unterschied zwischen dem Muster auf dieser Verbindung und meinem Beispielcode gibt.

Verwandte Themen