如何将项目添加到字典"并行循环安全"

时间:2014-04-01 15:37:59

标签: c# dictionary parallel.foreach

我有一个Parallel.ForEach循环做一些处理。但是第一个操作是在未包含密钥的情况下在字典中添加值。添加它时出错,它表示密钥已经在字典中。我猜这个密钥是在这个线程的.Contains检查之后但是在添加之前由并行进程添加的。除了将该行放在try-catch中之外,还有另一个我可以用来防止该错误的简单解决方案吗?

Parallel.ForEach(branchFixes, b =>
{
  Parallel.ForEach(b.Value, t =>
  {
    var team = t.Key;
    if (!resultTeamDict.ContainsKey(team))
    {
      resultTeamDict.Add(team, new Dictionary<FixItem, Dictionary<BranchInfo, bool>>());
    }
  });
});

3 个答案:

答案 0 :(得分:15)

即使在竞争条件之外,Dictionary<,>也不是线程安全的。您应该使用ConcurrentDictionary<,>,在这种情况下可能使用AddOrUpdate方法以原子方式执行修改。 (我假设您要为“嵌套”字典添加值。否则,请考虑TryAdd。)

答案 1 :(得分:4)

您可以在.NET 4.5中使用ConcurrentDictionary,并使用TryAdd替换ContainsKey和Add方法调用。见http://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx

答案 2 :(得分:2)

这是&#34;使用时间检查时间的教科书示例&#34;错误:在检查字典是否包含密钥和Add调用之间,另一个线程可能已经插入了该项,使Add的前提条件无效。

解决方案是使用ConcurrentDictionary<T>或相互排除的线程通过锁或其他同步工具同时更新字典。

您可能希望对代码进行概要分析,以检查触发线程是否值得 - 在这种情况下,开销可能非常高。