首页 文章详情

面试必备:聊聊C#中Parallel和ParallelQuery的用法

DotNet NB | 99 2022-08-08 23:48 0 0 0
UniSMS (合一短信)

简述

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; }    }

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


推荐阅读:
  API 工程化分享
  我的微软 MVP 之路
【译】ASP.NET Core 6 中的性能改进
【译】.NET 7 预览版 1 中的 ASP.NET Core 更新
【译】C# 11 特性的早期预览

点击下方卡片关注DotNet NB

一起交流学习

▲ 点击上方卡片关注DotNet NB,一起交流学习

请在公众号后台

回复 【路线图】获取.NET 2021开发者路线图
回复 【原创内容】获取公众号原创内容
回复 【峰会视频】获取.NET Conf开发者大会视频
回复 【个人简介】获取作者个人简介
回复 【年终总结】获取作者年终总结
回复 加群加入DotNet NB 交流学习群

长按识别下方二维码,或点击阅读原文。和我一起,交流学习,分享心得。


good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter