Parallel.Foreach Concurrent Dictionary 中一个键的值(Concurrent Bag)

Parallel.Foreach on values (Concurrent Bag) of one key in Concurrent Dictionary

我在将 ForEach 循环转换为 Parallel.ForEach 循环时遇到问题。

我有一个并发词典:

private readonly ConcurrentDictionary<string, ConcurrentBag<ParentClass>> ObjectDict = new();

其中包含:

对象A继承自ParentClass。

我的目标是循环遍历并发字典中一个键条目的并发包。

现在我正在努力将以下 ForEach 循环转换为 Parallel.ForEach

foreach (ObjectA objA in ObjectDict["Object A"])
{
     objA.ObjectASpecificMethod();
}

Parallel.ForEach(ObjectDict["Object A"], objA =>
{
     objA.ObjectASpecificMethod();
}

问题是 objA 不是 ObjectA 类型,而是并发字典 ObjectDict 中定义的 ParentClass 类型。但是 ParentClass 没有 Childclass 具体方法。

我希望我能正确地澄清自己。

您可以指定类型,就像您在常规 foreach:

中所做的那样
    Parallel.ForEach(ObjectDict["Object A"], (ObjectsA objectA) =>
    {
         objectA.ObjectASpecificMethod();
    }

发现问题:即使 ConcurrentBag 中的所有对象都属于相同的对象类型,它也被作为非通用集合处理。这可能是因为ConcurrentBag被指定为ParentClass,但是里面的Objects是ChildClass的。

为了解决这个问题,我找到了 2 种方法:

  1. 像这里描述的那样转换正确的对象类型:https://devblogs.microsoft.com/pfxteam/faq-parallel-foreach-and-non-generic-collections/

    Parallel.ForEach(ObjectDict["Object A"].Cast<ObjectA>(), objA =>
    {
          objA.ObjectASpecificMethod();
    }
    
  2. 用正确的对象类型指定非泛型集合的类型

    Parallel.ForEach(ObjectDict["Object A"].OfType<ObjectA>(), objA =>
    {
         objA.ObjectASpecificMethod();
    }
    

要使这两种方法都起作用,您需要使用 System.Linq!

两者都经过测试,它们似乎都提供了有效的结果。 也许有知识的人可以详细说明差异。