在.Net中AsParallel().ForAll和ForEach性能对比

发布时间 2023-11-02 16:52:07作者: 喜东东三三

在.Net中AsParallel().ForAll和ForEach性能对比

Array.AsParallel().ForAll(){}

AsParallel().ForAll 是 C# 中用于并行处理集合元素的方法。它允许您以并行的方式对集合中的每个元素执行指定的操作。

AsParallel() 是一个扩展方法,它将一个普通的可枚举集合转换为一个并行查询。通过将查询转换为并行查询,可以利用多核处理器和多线程来并行处理集合中的元素,以提高执行效率。

ForAll() 是并行查询的一个终止操作,它对并行查询中的每个元素执行指定的操作。与普通的 foreach 循环不同,ForAll() 方法可以并行地处理集合中的元素,从而提高处理速度。

以下是使用 AsParallel().ForAll 方法的一些注意事项:

  1. AsParallel() 方法只有在集合中的元素数量较大时才会带来性能上的提升。对于较小的集合,串行处理可能更快。

  2. ForAll() 方法是一个阻塞操作,它会等待所有并行任务完成后才会返回。因此,如果您需要并行处理集合元素但不需要等待结果,可以考虑使用 Parallel.ForEach() 方法。

  3. 并行处理集合时,操作的执行顺序可能与元素在集合中的顺序不一致。如果您需要保持操作的顺序,可以使用 AsOrdered() 方法。

  4. 并行处理集合时,操作必须是线程安全的。确保在操作中不会修改共享的状态或资源,或者使用适当的同步机制来处理共享状态。

总之,AsParallel().ForAll 方法可以帮助您以并行的方式高效地处理大型集合中的元素,从而提高程序的性能。但请注意在使用并行处理时要谨慎处理共享状态和资源,以避免并发问题。

Array.ForEach(){}

ForEach() 是 C# 中用于遍历集合元素并执行指定操作的方法。与 AsParallel().ForAll() 不同,ForEach() 方法是在单线程中按顺序处理集合元素的。

以下是关于 ForEach() 方法的一些特点和注意事项:

  1. ForEach() 方法是一个阻塞操作,它会按顺序遍历集合中的每个元素并执行指定的操作。

  2. ForEach() 方法适用于小型集合或不需要并行处理的场景。对于大型集合或需要并行处理的场景,可以考虑使用 AsParallel().ForAll() 方法来提高处理速度。

  3. ForEach() 方法不能保证操作的执行顺序与集合中元素的顺序一致。如果需要保持操作的顺序,可以使用普通的 foreach 循环。

  4. 在操作中要注意线程安全性,确保不会修改共享的状态或资源。如果需要修改共享状态,应使用适当的同步机制来确保线程安全。

  5. ForEach() 方法是 List 类的扩展方法,因此只能应用于 List 类型的集合。如果要在其他类型的集合上使用 ForEach(),可以先将其转换为 List

    对比示例代码

    创建一个新的控制台应用,复制下列代码并运行

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;

public class Program
{
    private static List<int> currentCountList = new List<int> ();
    private static int currentCount = 0;
    private static int currentCount1 = 0;
    private static int currentCount2 = 0;
    private static int currentCount3 = 0;

    public static void Main(string[] args)
    {
  for (int i = 0; i < 900000000; i++)
  {
      currentCountList.Add(i);
  }
        Stopwatch stopwatch = new Stopwatch();

        // 测试 IncrementCount 方法的运行时间
        stopwatch.Start();
        IncrementCount();
        stopwatch.Stop();
        Console.WriteLine($"IncrementCount 方法的运行时间:{stopwatch.Elapsed}");

        // 测试 IncrementCount1 方法的运行时间
        stopwatch.Reset();
        stopwatch.Start();
        IncrementCount1();
        stopwatch.Stop();
        Console.WriteLine($"IncrementCount1 方法的运行时间:{stopwatch.Elapsed}");
    }

    private static void IncrementCount()
    {
        currentCountList.AsParallel().ForAll(p =>
        {
            currentCount++;
            currentCount1++;
        });
    }

    private static void IncrementCount1()
    {
        currentCountList.ForEach(p =>
        {
            currentCount2++;
            currentCount3++;
        });
    }
}

最终显示结果

IncrementCount 方法的运行时间:00:00:00.0537029
IncrementCount1 方法的运行时间:00:00:00.0002007

最终结果显示,在数据量少的情况下,Array.ForEach(){}的运行速度比Array.AsParallel().ForAll(){}要快上很多,所以在使用的时候需要结合当前实际情况决定.