2011-01-12 6 views
0

スレッドが更新しているアイテムの辞書があります。別のスレッドを使用して更新されたアイテムのリストを取得するメソッドが必要です。そのようスレッドによって更新されているコレクションのオブジェクトのリストを取得

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

ModelFacade._totalListOfStkObjectsは、スレッドによって更新されているコレクションです。私は例外を取得し続けます: "コレクションが変更された:列挙操作が実行されません。 _totalListOfStkObjectsをローカルコレクションにコピーし、GetListOfEntities()でそれを反復しようとしましたが、同じエラーが発生します..

助けが必要ですか?

WulfgarPro

+0

絶対に2つのスレッドで辞書にアクセスする必要がありますか?そうでなければ、生産者/消費者のパターンのような選択肢があります。 – Jacob

+0

1つのスレッドがコレクションを満たすために外部アプリケーションに照会します。もう1つのスレッドはListBoxをアイテムで更新します。プロデューサ/コンシューマの設定例 – wulfgarpro

+0

@WulfgarProプロデューサー/消費者のパターンのように見えます。 –

答えて

2

辞書にアクセスするための保証、スレッドセーフな方法があるように行っていません。

object dictLock = new object(); 

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

は別のスレッドでそれを変更する際にも、辞書をロックしていることを確認してください:あなたの最善の策は、あなたがコレクションを共有していないようにコードを変更するか、またはアクセスしたときに辞書をロックすることです。

2

.NET 4を使用している場合は、DictionaryConcurrentDictionaryに変更してください。質問をシミュレートして解決する簡単な例があります。

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

スレッドセーフなシングルトンクラスで辞書をラップすることができます。これにより、ConcurrentDictionaryのすべての機能がDictionaryに提供されます。ディクショナリを参照するには、間接指定の追加レイヤーが1つだけ必要です。

参考:

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

宣言:C#でのシングルトンパターンの詳細については

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; 
     } 
    } 
} 

ルックhere。このリンクのパターンと私のコード例の違いは1つだけです。

関連する問題