在任何情况下是否有任何理由选择Parallel.ForEach而不是等待ForEachAsync(反之亦然)?还是几乎相同?
await collection.ForEachAsync( m => { m.DoSomething(); } );
VS
Parallel.ForEach( collection, m => { m.DoSomething(); } );
答案 0 :(得分:2)
它们根本不是“几乎相同”。
使用Parallel类中的函数(例如Parallel.ForEach()
)时,您正在调用某些操作,其中该操作被分解为多个较小的操作,每个操作均在不同的线程上执行(又称为多线程)。线程)。
ForEachAsync
不一定是多线程的。它是异步的,并且异步操作不是多线程的(嗯,它们可以,但不一定是,取决于实现)。
我强烈建议您阅读以下post,其中将详细介绍该主题。
关于您的问题
在任何情况下是否有任何理由选择Parallel.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要差
在这里,我再次运行相同的代码,但是得到了diff结果
之所以如此,是因为存在线程,编译器将线程划分为多个,并且每个列表都运行分配给它的项目 下图显示了差异线程
但是当您运行以下代码时
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}"));
您只能在此处显示一个线程
加上数据打印将始终按照列表的相同顺序运行
我希望这个答案能解释区别!
答案 2 :(得分:0)
在任何情况下是否有任何理由选择Parallel.ForEach而不是等待ForEachAsync(反之亦然)?
Parallel.ForEach
用于同步代码。它的委托必须是同步的,并且必须被同步调用。
ForEachAsync
不是标准算法。有几种不同的实现,但是通常它们会尝试将异步和并行性混合在一起。他们必须放弃Parallel.ForEach
的某些自我平衡方面。绝大多数代码不需要ForEachAsync
;大多数代码是 异步或并行。