.NET Dictionary:潜在的并发问题?

Ace*_*Ace 8 .net c# concurrency dictionary locking

我正在努力维护.NET项目,我遇到了一些麻烦,我很乐意和你们分享=)

问题代码:

if( evilDict.Count < 1 )
{
    foreach (Item item in GetAnotherDict())
        if (!evilDict.containsKey(item.name.ToLower().Trim()))
            evilDict.add(item.name.ToLower().Trim(), item.ID);
}
Run Code Online (Sandbox Code Playgroud)

尽管contains() - 检查,我收到一个ArgumentException告诉我已经添加了一个具有相同键的项目.我们只是在生产中遇到这个问题,从未进行过测试,这让我怀疑是并发问题.我想知道的是:

  • 你认为这是并发问题吗?
  • 我如何解决它?
  • 我的修复是否可行(见下文)?
  • 这是我对.NET的第一次尝试,字典通常是问题的根源吗?

这是我的潜在修复,取代了dictionary.add()的东西

protected static void DictAddHelper(Dictionary<String, int> dict, String key, int value)
{
    lock (dict)
    {
        key = key.ToLower().Trim();
        if (dict.ContainsKey(key) == false)
        {
            try
            {
                dict.Add(key, value);
            }
            catch (ArgumentException aex)
            {
                StringBuilder debugInfo = new StringBuilder();
                debugInfo.AppendLine("An argumentException has occured: " + aex.Message);
                debugInfo.AppendLine("key = " + key);
                debugInfo.AppendLine("value = " + value);
                debugInfo.AppendLine("---Dictionary contains---");

                foreach (String k in dict.Keys)
                    debugInfo.AppendLine(k + " = " + dict[k]);

                log.Error(debugInfo, aex);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

建议不要求我做一个线程安全的Dict类实现更好,因为这将是一个非常大的重构,不会是一个非常受欢迎的建议=)

EDIT2:

我试过了

lock (((IDictionary)dict).SyncRoot)
Run Code Online (Sandbox Code Playgroud)

但我明白了

Error   28  Using the generic type 'System.Collections.Generic.IDictionary<TKey,TValue>' requires '2' type arguments    
Run Code Online (Sandbox Code Playgroud)

然后我试试这个:

lock (((IDictionary<String, int>)dict).SyncRoot)
Run Code Online (Sandbox Code Playgroud)

错误:

Error   28  'System.Collections.Generic.IDictionary<string,int>' does not contain a definition for 'SyncRoot'
Run Code Online (Sandbox Code Playgroud)

最终编辑(我猜):

感谢所有的答案!

现在,我想知道的就是这个.我的方法(DictAddHelper)会不会起作用,如果没有,为什么?

Meg*_*can 6

如果您怀疑访问字典时出现并发问题,那么您的修复程序将没有任何用处.它将解决您遇到的特定问题,但是如果您同时访问该字典,将来会遇到更多问题.

在修改字典时,请考虑锁定对字典的访问.


San*_*nen 1

不应该

if (!evilDict.contains(item.name.ToLower().Trim()))
Run Code Online (Sandbox Code Playgroud)

if (!evilDict.ContainsKey(item.name.ToLower().Trim()))
Run Code Online (Sandbox Code Playgroud)