将Sequential foreach替换为Parallel.foreach

本文关键字:foreach Parallel 替换 Sequential | 更新日期: 2023-09-27 18:26:27

在下面的foreach p : allPersons中,很明显(因为逻辑是顺序的)映射/字典可以用于缓存/记忆。

Dictionary<string, int> personNameToIdMap = new Dictionary<string, int>();
foreach(p : allPersons)
{
 int outputId;
 if(personNameToIdMap.TryGetValue(p.Name, out outputId))
 {
   // nothing to do since map contained the p.Name
 }
 else
 { 
    outputId = doExpensiveLookup(p.Name);
    personNameToIdMap[p.Name] = outputId;
 }
  ...
  p.Id = outputId;
}

如果我用Parallel.ForEach替换上面的foreach,每个线程会共享personNameToIdMap吗?

将Sequential foreach替换为Parallel.foreach

是的,在Parallel.Foreach的情况下,每个线程将使用相同的Dictionary实例。

如果你真的想要并行,你可以使用ConcurrentDictionary,它是Dictionary 的线程安全版本

Harris是完全正确的-ConcurrentDictionary<T,U>将是正确的方法。考虑到这一点,您可能需要稍微改变您的方法,以利用ConcurrentDictionaryGetOrAdd方法:

ConcurrentDictionary<string, int> personNameToIdMap = new ConcurrentDictionary<string, int>();
Parallel.ForEach(allPersons, p =>
{
    int outputId = personNameToIdMap.GetOrAdd(p.Name, name => doExpensiveLookup(p.Name));
    // ...
    p.Id = outputId;
}