33

いくつかのタスク内で辞書を使用しています。

論理的には、キーが衝突しないように設定しましたが、ディクショナリに追加しているときにこの例外が発生することがあります。

Index was outside the bounds of the array.
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Rpc.<MapIntoRpc>b__4[T](Object x) in Rpc.cs:line 113
   at System.Threading.Tasks.Task`1.InvokeFuture(Object futureAsObj)
   at System.Threading.Tasks.Task.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()

同じキーを複数回削除または追加しようとすると、同時実行の問題が発生する可能性があることは理解していますが、それをアルゴリズムで説明しました。

追加が時々失敗する原因は何ですか? それを回避する最善の方法は何ですか?

4

3 に答える 3

54

ドキュメントを参照する必要がありました。それが言うこと:

コレクションが変更されない限り、ディクショナリは複数のリーダーを同時にサポートできます。それでも、コレクションの列挙は本質的にスレッドセーフな手順ではありません。列挙が書き込みアクセスと競合するまれなケースでは、列挙全体の間、コレクションをロックする必要があります。読み取りおよび書き込みのために複数のスレッドがコレクションにアクセスできるようにするには、独自の同期を実装する必要があります。スレッドセーフな代替手段については、ConcurrentDictionary を参照してください。

于 2013-02-26T17:58:29.173 に答える
23

あなたの問題はおそらく同期です。ディクショナリが追加されると、基礎となる構造 (配列) のサイズを大きくする必要がある場合があります。複数のスレッドから追加すると、IndexOutOfRangeException. 安全な方法で追加していることを確認するには、ロックなどを使用する必要があります。

または、スレッドセーフなコレクションであるConcurrentDictionaryを使用できます。

于 2013-02-26T18:00:43.997 に答える
16

だからあなたは思うかもしれませんWhatever! it will just break the one time-しかしいいえ:

重要: 辞書が壊れたら、それは壊れています。

デバッグ目的で追加されたディクショナリが読み取られることさえなかったため、(IIS がスケジュールに従ってリサイクルされるまで) 3 時間の売り上げが発生します。

ここに画像の説明を入力

注:これは、この状態になる前に 3.5 年間実行されていました。

 private Dictionary<string, string> _debugLookup;

 _debugLookup[key] = virtualPath;

これは静的辞書でさえありませんでしたIViewLocationCache。インスタンス メソッドである MVC でした。

于 2016-10-01T18:00:44.263 に答える