7

最近、一般的な辞書を使用しているときに次の例外が発生していました

InvalidOperationException が発生しました。コレクションが変更されました

このエラーの主な原因は、使用していた静的辞書のスレッド セーフの問題であることがわかりました。

ちょっとした背景: 私は現在、この問題に関連する 3 つの異なるメソッドを持つアプリケーションを持っています。

  1. メソッド A は、値を使用してディクショナリを反復処理しforeach、値を返します。
  2. メソッド B はデータをディクショナリに追加します。
  3. メソッド C は、ディクショナリ内のキーの値を変更します。

ディクショナリを繰り返し処理しているときに、データも追加されることがあり、これがこの問題の原因です。foreach辞書の内容を繰り返し処理するコードの部分で、この例外が発生し続けます。この問題を解決するために、ジェネリック ディクショナリを に置き換えました。実行ConcurrentDictionaryした内容の詳細は次のとおりです。

目的:私の主な目的は、例外を完全に削除することです

メソッドB(辞書に新しいキーを追加する)の場合、次のように置き換え.AddましたTryAdd

メソッド C (辞書の値を更新する) については、何も変更しませんでした。コードの大まかなスケッチは次のとおりです。

  static public int ChangeContent(int para)
  {
      foreach (KeyValuePair<string, CustObject> pair in static_container)
      {
             if (pair.Value.propA != para ) //Pending cancel 
             {
                pair.Value.data_id = prim_id;    //I am updating the content
                return 0;

             }
      }
     return -2;
  }

メソッド A の場合- ディクショナリを反復処理しているだけで、ここで実行中のコードが (デバッグ モードで) 停止し、Visual Studio からエラーが発生した場所であることが通知されます。使用しているコードは次のようなものです。

    static public CustObject RetrieveOrderDetails(int para)
    {
            foreach (KeyValuePair<string, CustObject> pair in static_container)
            {                   
                if (pair.Value.cust_id.Equals(symbol))
                {
                    if (pair.Value.OrderStatus != para) 
                    {
                       return pair.Value; //Found
                    }
                }
            }
            return null; //Not found
    }

これらの変更により、発生している例外が解決されますか?

編集:

このページでは、このメソッドを使用すると、書き込みと並行して要素をトラバースできると述べてGetEnumeratorいます (ただし、時代遅れかもしれません)。foreach を使用するのと同じではありませんか?

4

2 に答える 2

1

実行する前foreach()に、コンテナを新しいインスタンスにコピーしてみてください

var unboundContainer = static_container.ToList();
foreach (KeyValuePair<string, CustObject> pair in unboundContainer)

また、プロパティの更新はスレッドセーフの観点から正しくないと思います。代わりにValueコードをリファクタリングして使用してください。TryUpdate()

于 2013-02-20T09:35:13.463 に答える