c# - 这两种方法的行为是否相同?
问题描述
以下两个代码并行处理列表中的项目,并行度阈值为 5。它们实际上是否相同?
Parallel.ForEach 与 MaxDegreeOfParallelism
public async Task Run()
{
var list = // List<....>
Parallel.ForEach(list,
new ParallelOptions { MaxDegreeOfParallelism = 5}, d => {
....
process(d).RunSynchronously();
....
});
}
扩展方法使用Partitioner.Create(...).GetPartitions(...)
public async Task Run()
{
var list = // List<....>
await list.ForEachAsync(list.Count() / 5 + 1, async d =>
{
....
await process(d);
....
});
}
public static class Extension
{
public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
return Task.WhenAll(
from partition in Partitioner.Create(source).GetPartitions(dop)
select Task.Run(async delegate {
using (partition)
while (partition.MoveNext())
await body(partition.Current);
}));
}
}
解决方案
Parallel.Foreach
使用默认分区程序。如果您有一个小工作要执行,那么这可能是开销,因为每个分区都将被计算并且每个分区都将是每次迭代都会调用的委托。
可以使用分区来修复此开销。它使您能够为委托主体提供顺序循环,以便每个分区仅调用一次委托,而不是每次迭代调用一次。您也可以使用分区程序来控制分区。
Parallel.ForEach(Partitioner.Create(0L, SUMTOP), (range) =>
{
long local = 0;
for (long i = range.Item1; i < range.Item2; i++) local += i;
Interlocked.Add(ref sum, local);
});
第二个实现做类似的工作,但异步,你有更多的分区命令。它将处理小型工作的开销。希望这个解释能帮助你做出选择。
推荐阅读
- c - C语言中的套接字通信。发送文件内容
- c# - 将变量从另一个类传递到表单中
- c - C程序正在自动关闭
- swift - 图像压缩而不快速改变图像的分辨率
- makefile - 为什么在配方中使用 $(MAKE) 制作“--dry-run”会导致错误?
- xcode - 有没有办法在不手动选择所有目标或使用插件的情况下将文件添加到所有 Xcode 目标
- python-3.x - 使用python通过3D点进行平面拟合
- html - 为什么我的 css 文件导入不起作用?
- java - 在不同的 Maven 模块中测试多个实现?
- mysql - 使用 docker-compose.yml 的 tomcat + mysql + war