Parallel.ForEach和await ForEachAsync之间的区别

时间:2019-03-27 17:03:03

标签: c# parallel-processing parallel.foreach

在任何情况下是否有任何理由选择Para​​llel.ForEach而不是等待ForEachAsync(反之亦然)?还是几乎相同?

await collection.ForEachAsync( m => { m.DoSomething(); } );

VS

Parallel.ForEach( collection, m => { m.DoSomething(); } );

3 个答案:

答案 0 :(得分:2)

它们根本不是“几乎相同”。

使用Parallel类中的函数(例如Parallel.ForEach())时,您正在调用某些操作,其中该操作被分解为多个较小的操作,每个操作均在不同的线程上执行(又称为多线程)。线程)。

另一方面,

ForEachAsync不一定是多线程的。它是异步的,并且异步操作不是多线程的(嗯,它们可以,但不一定是,取决于实现)。

我强烈建议您阅读以下post,其中将详细介绍该主题。

关于您的问题

  

在任何情况下是否有任何理由选择Para​​llel.ForEach而不是等待ForEachAsync

绝对可以肯定,这样做的理由是有原因的,但是为了确定您将使用哪种方案,您必须同时了解它们。

这是一个简单的例子:

您有一个对象集合,并且想要遍历它们并执行某种操作。您是否关心这些动作的发生顺序?如果这样,请不要使用Parallel.ForEach(),因为不能保证调用它们的顺序(由于其多线程性质)。

编辑:

在您的示例中,这完全取决于collection中有多少项以及DoSomething()的处理繁重程度。

之所以这样做是因为Parallel.ForEach()非免费的。需要权衡取舍。设置多线程环境需要花费时间,并且如果collection很小和/或DoSomething()花费的时间不长,那么设置这些线程所花费的时间将是单线程异步操作花费更好(通常更快)。

另一方面,如果collection很大和/或DoSomething()是一个繁重的任务,那么Parallel.ForEach()无疑是性能最高的选择。

答案 1 :(得分:0)

这完全取决于线程 假设您有以下课程

public class person
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

这是你的主要班级

List<person> persons = new List<person>()
            {
                new person{ ID = 1,Name="Ali"}
                ,new person{ ID = 2,Name="Gorge"}
                ,new person{ ID = 3,Name="Alex"}
                ,new person{ ID = 4,Name="Liz"}
                ,new person{ ID = 5,Name="Scott"}
                ,new person{ ID = 6,Name="Abby"}
                ,new person{ ID = 7,Name="Sarah"}
            };

            Parallel.ForEach(persons, (p) =>
            {
                Console.WriteLine($"Id : {p.ID} ,Name : {p.Name}");
            });

当您运行此代码时,列表项将被拆分到diff线程上,并且代码将不会按顺序运行,如您在以下输出中看到的那样,我得到的打印顺序比原始List要差 enter image description here

在这里,我再次运行相同的代码,但是得到了diff结果

enter image description here

之所以如此,是因为存在线程,编译器将线程划分为多个,并且每个列表都运行分配给它的项目 下图显示了差异线程

enter image description here

但是当您运行以下代码时

List<person> persons = new List<person>()
            {
                new person{ ID = 1,Name="Ali"}
                ,new person{ ID = 2,Name="Gorge"}
                ,new person{ ID = 3,Name="Alex"}
                ,new person{ ID = 4,Name="Liz"}
                ,new person{ ID = 5,Name="Scott"}
                ,new person{ ID = 6,Name="Abby"}
                ,new person{ ID = 7,Name="Sarah"}
            };

            await persons.ForEachAsync(async p => Console.WriteLine($"Id : {p.ID} ,Name : {p.Name}"));

您只能在此处显示一个线程

enter image description here

加上数据打印将始终按照列表的相同顺序运行

我希望这个答案能解释区别!

答案 2 :(得分:0)

  

在任何情况下是否有任何理由选择Para​​llel.ForEach而不是等待ForEachAsync(反之亦然)?

Parallel.ForEach用于同步代码。它的委托必须是同步的,并且必须被同步调用。

ForEachAsync不是标准算法。有几种不同的实现,但是通常它们会尝试将异步和并行性混合在一起。他们必须放弃Parallel.ForEach的某些自我平衡方面。绝大多数代码不需要ForEachAsync;大多数代码是 异步并行。