简述

Parallel:提供对并行循环和区域的支持,Parallel 主要提供了 For 系列方法和 ForEach 系列方法,并行处理所有项。两个系列的方法都有若干重载,但最常用也最易用的是这两个。
ParallelQuery:ParallelQuery是linq的并行扩展方法,可以通过IEnumerable.AsParallel() 来实现。

Parallel例子

  1. Parallel.For(int fromInclude, int toExclude, Action body)

Parallel.For 类似for循环,区别是Parallel.For 是异步处理多条数据,意味着它是无序输出。

  1. Parallel.For(0, 6, (i) => {
  2. Console.Write($"{i} ");
  3. });
  4. Console.WriteLine();
  5. //输出 可能为:0 4 1 3 5 2
  1. Parallel.ForEach(IEnumerable, Action)

那么Parallel.ForEach就是异步的foreach,仿照上面离职改造一下

  1. var all = new [] { 0, 1, 2, 3, 4, 5, 6};
  2. Parallel.ForEach(all, (i) => {
  3. Console.Write($"{i} ");
  4. });
  5. Console.WriteLine();
  6. //输出 可能为:0 4 5 3 1 2

Parallel优缺点

Parallel有啥优点?
从语法来说,Parallel.For 和 Parallel.ForEach比原生的for 和 foreach难用,那么有啥有点呢?Parallel主要还是用到异步,大批量数据处理速度上占有优势,但是不考虑顺序的前提下。
Parallel有啥缺点?
“并行”异步会涉及到线程安全问题。还好有解决方案,可以用Interlocked,Interlocked提供了一些简单计算原子操作,可以去查询一下相关资料。

使用案例

  1. public static int CalcFactorial(int n)
  2. {
  3. return n <= 2 ? n:n * CalcFactorial(n - 1);
  4. }
  5. public static int SumFactorial()
  6. {
  7. int[] datas = { 4, 5, 7, 9 };
  8. int sum = 0;
  9. Parallel.ForEach(datas, n => {
  10. Interlocked.Add(ref sum, CalcFactorial(n));
  11. });
  12. return sum;
  13. }

ParallelQuery 使用案例

跟上面一样,计算阶乘

  1. public static int CalcFactorial(int n)
  2. {
  3. return n <= 2 ? n:n * CalcFactorial(n - 1);
  4. }
  5. public static int SumFactorials()
  6. {
  7. int[] datas = { 4, 5, 7, 9 };
  8. return datas.AsParallel().Select(s => CalcFactorial(s)).Sum();
  9. }

还可以这样用

  1. ConcurrentQueue<Product> products = new ConcurrentQueue<Product>();
  2. /*向集合中添加多条数据*/
  3. Parallel.For(0, 600, (num) =>
  4. {
  5. products.Enqueue(new Product() { Category = "Category" + num, Name = "Name" + num, SellPrice = num });
  6. });
  7. CancellationTokenSource cts = new CancellationTokenSource();
  8. /*创建tk1 任务 查询 符合 条件的数据*/
  9. Task<ParallelQuery<Product>> tk1 = new Task<ParallelQuery<Product>>((ct) =>
  10. {
  11. Console.WriteLine("开始执行 tk1 任务", products.Count);
  12. Console.WriteLine("tk1 start任务中 数据结果集数量为:{0}", products.Count);
  13. var result = products.AsParallel().Where(p => p.Name.Contains("1") && p.Name.Contains("2"));
  14. Console.WriteLine("tk1 end任务中 数据结果集数量为:{0}", result.Count());
  15. return result;
  16. }, cts.Token);
  17. tk1.Start();
  18. Task.WaitAll(tk1);
  19. Console.WriteLine("tk1任务结果输出,筛选后记录总数为:{0}", tk1.Result.Count());
  20. tk1.Dispose();
  21. cts.Dispose();
  22. Console.ReadLine();
  23. //Product类
  24. class Product
  25. {
  26. public string Name { get; set; }
  27. public string Category { get; set; }
  28. public int SellPrice { get; set; }
  29. }

具体用法请查看相关资料。