聊聊C#中Parallel和ParallelQuery的用法

简述

Parallel:提供对并行循环和区域的支持,Parallel 主要提供了 For 系列方法和 ForEach 系列方法,并行处理所有项。两个系列的方法都有若干重载,但最常用也最易用的是这两个。

ParallelQuery:ParallelQuery<T>是linq的并行扩展方法,可以通过IEnumerable<T>.AsParallel() 来实现。.

Parallel例子

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

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

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

2、Parallel.ForEach<T>(IEnumerable<T>, Action<T>)

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

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

Parallel有啥优点?

从语法来说,Parallel.For 和 Parallel.ForEach比原生的for 和 foreach难用,那么有啥有点呢?Parallel主要还是用到异步,大批量数据处理速度上占有优势,但是不考虑顺序的前提下。

Parallel有啥缺点?

“并行”异步会涉及到线程安全问题。还好有解决方案,可以用Interlocked,Interlocked提供了一些简单计算原子操作,可以去查询一下相关资料。

使用案例

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

ParallelQuery 使用案例

跟上面一样,计算阶乘

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

还可以这样用

 ConcurrentQueue<Product> products = new ConcurrentQueue<Product>();            /*向集合中添加多条数据*/            Parallel.For(0, 600, (num) =>            {                products.Enqueue(new Product() { Category = "Category" + num, Name = "Name" + num, SellPrice = num });            });            CancellationTokenSource cts = new CancellationTokenSource();            /*创建tk1 任务  查询 符合 条件的数据*/            Task<ParallelQuery<Product>> tk1 = new Task<ParallelQuery<Product>>((ct) =>            {                Console.WriteLine("开始执行 tk1 任务", products.Count);                Console.WriteLine("tk1 start任务中 数据结果集数量为:{0}", products.Count);                var result = products.AsParallel().Where(p => p.Name.Contains("1") && p.Name.Contains("2"));                Console.WriteLine("tk1 end任务中 数据结果集数量为:{0}", result.Count());                return result;            }, cts.Token);            tk1.Start();            Task.WaitAll(tk1);            Console.WriteLine("tk1任务结果输出,筛选后记录总数为:{0}", tk1.Result.Count());            tk1.Dispose();            cts.Dispose();            Console.ReadLine();//Product类 class Product    {        public string Name { get; set; }        public string Category { get; set; }        public int SellPrice { get; set; }    }

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