正确的方法来锁定字典对象

Paw*_*iya 16 c# multithreading dictionary locking syncroot

在我的代码中,我有一个静态字典对象

private static IDictionary< ConnKey, DbConnection > ConnectionList = new Dictionary< ConnKey, DbConnection >( );
Run Code Online (Sandbox Code Playgroud)

这就是抛出这个错误

System.IndexOutOfRangeException: 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)
Run Code Online (Sandbox Code Playgroud)

我搜索并发现这是因为多个线程尝试访问字典,但我确实lock在字典上

lock( ConnectionList ) {
   ConnectionList.Add( key, res );
}
Run Code Online (Sandbox Code Playgroud)

然后我搜索了更多,发现字典上的锁并没有阻止它上面的所有操作,所以我应该像这样使用lock它的SyncRoot对象来实现我想要的

lock( ((IDictionary)ConnectionList).SyncRoot) {
Run Code Online (Sandbox Code Playgroud)

但后来我搜索到使用SyncRoot不是一个好习惯

在进一步搜索中,我发现有一个ConcurrentDictionary用于此目的

  1. 那么任何人都可以建议我哪个是锁定字典的最佳方法
  2. 如果我使用ConcurrentDictionary,我仍然需要使用lock它或它将自己处理一切.
  3. 如果我必须使用锁定ConcurrentDictionary,我必须lock直接或再次使用它我必须SyncRoot为它锁定对象

提前致谢!

xan*_*tos 19

随着Dictionary<,>你必须同时锁定读取和写入.所以两者

lock( ConnectionList ) {
   ConnectionList.Add( key, res );
}
Run Code Online (Sandbox Code Playgroud)

lock( ConnectionList ) {
   res = ConnectionList[ key ];
}
Run Code Online (Sandbox Code Playgroud)

lock( ConnectionList ) {
   int cnt = ConnectionList.Count;
}
Run Code Online (Sandbox Code Playgroud)

lock( ConnectionList ) {
   ConnectionList.Clear();
}
Run Code Online (Sandbox Code Playgroud)

lock( ConnectionList ) {
   foreach ( var kv in ConnectionList ) {
      // Do things
   }
}
Run Code Online (Sandbox Code Playgroud)

等等 :-)

随着ConcurrentDictionary<,>你不需要任何锁定,但要注意的语法比的一个有点不同Dictionary<,>