【C#】并行编程实战:使用 PLINQ(2)

news2024/11/16 11:54:03

         PLINQ 是语言集成查询(Language Integrate Query , LINQ)的并行实现(P 表示并行)。本章将继续介绍其编程的各个方面以及与之相关的一些优缺点。

        本文的主要内容为 PLINQ 中的合并选项以及抛出和处理异常。

        本教程对应学习工程:魔术师Dix / HandsOnParallelProgramming · GitCode      


4、PLINQ 中的合并选项

        如前文所述,当创建并行查询时,将对源集合进行分区,以便多个任务可以同时在各部分上工作。查询完成后,需要合并结果,以便将其提供给使用他的线程。

4.1、使用 NotBuffered 合并选项

        使用 NoBuffered 合并选项时,并发任务的结果不被缓冲。一旦完成任何任务,他们就会将结果返回给使用的线程。代码演示如下:

        private void RunWithNotBuffered()
        {
            var task = Task.Run(() =>
                 {
                     Debug.Log("RunWithNotBuffered Start !");
                     var L = ParallelEnumerable.Range(0, 10);
                     var notBufferedQuery = L.WithMergeOptions(ParallelMergeOptions.NotBuffered)
                         .Select(async x =>
                         {
                             await Task.Delay(x * 1000);
                             return x;
                         });

                     notBufferedQuery.ForEach(t=>
                     {
                         Debug.Log($"{t.Result} In  notBufferedQuery !");
                     });
                     Debug.Log("RunWithNotBuffered End !");
                 });
        }

        打印结果如下:

         首先,这个执行是无序的;然后虽然每一次选择都有等待,但是每有一个 Select 语句执行完成就会在 ForEach 里执行一次。

4.2、使用 AutoBuffered 合并选项

        使用 AutoBuffered 合并选项时,并发任务的结果将被缓冲,并使缓冲区可定期用于使用他的线程。根据集合的大小,可能会返回多个缓冲区。设置此选项后,使用结果的线程将需要等待更长的时间才能获得第一个结果。这也是默认选项。

        private void RunWithAutoBuffered()
        {
            var task = Task.Run(() =>
            {
                Debug.Log("RunWithAutoBuffered Start !");
                var L = ParallelEnumerable.Range(0, 10);
                var autoBufferedQuery = L.WithMergeOptions(ParallelMergeOptions.AutoBuffered)
                    .Select(async x =>
                    {
                        await Task.Delay(x * 1000);
                        return x;
                    });

                autoBufferedQuery.ForEach(t =>
                {
                    Debug.Log($"{t.Result} In  autoBufferedQuery !");
                });
                Debug.Log("RunWithAutoBuffered End !");
            });
        }

        这次打印的结果就比较有意思了:

         可以看到第一个结果出来等待了很久(8s),但是后面的结果就很快出来了。

4.3、使用 FullyBuffered 合并选项

        使用 FullyBuffered 合并选项时,并发任务的结果在进入使用它的线程之前会被完全缓冲。尽管获得第一个结果所花费的时间会更长,但是可以提高整体性能。

        测试代码如下:

        private void RunWithFullyBuffered()
        {
            var task = Task.Run(() =>
            {
                Debug.Log("RunWithFullyBuffered Start !");
                var L = ParallelEnumerable.Range(0, 10);
                var fullyBufferedQuery = L.WithMergeOptions(ParallelMergeOptions.FullyBuffered)
                    .Select(async x =>
                    {
                        await Task.Delay(x * 1000);
                        return x;
                    });

                fullyBufferedQuery.ForEach(t =>
                {
                    Debug.Log($"{t.Result} In  fullyBufferedQuery !");
                });
                Debug.Log("RunWithFullyBuffered End !");
            });
        }

        打印结果如下:

         可以看到依次打印出了结果,这是因为我们在等待时设置的代码是 (x*1000) ,也就是 Select 项目都是同时开始的,然后依次结束。

        并非所有查询运算符都支持全部的合并模式,运算符及其合并模式限制可参考以下网站:

PLINQ 中的合并选项 | Microsoft Learn详细了解:PLINQ 中的合并选项icon-default.png?t=N658https://learn.microsoft.com/zh-cn/dotnet/standard/parallel-programming/merge-options-in-plinq#query-operators-that-support-merge-options        除上述运算符外,ForAll 始终为 NotBuffered ,而 OrderBy 始终为 FullyBuffered。如果在这些运算符上制定了任何自定义的合并选项,则它们都会被忽略。

5、使用 PLINQ 抛出和处理异常

        简单地使用 TryCatch 语句就能获取到 PLINQ 中的异常:

        private void RunException()
        {
            var range = ParallelEnumerable.Range(1, 10);
            var query = range.Select(x => x / (x % 2 - 1));
            try
            {
                query.ForAll(x => Debug.Log(x));
            }
            catch (AggregateException ex)
            {
                Debug.LogError(ex.Message);
                var exs = ex.InnerExceptions;
                foreach (var innerEx in exs)
                {
                    Debug.LogError(innerEx.Message);
                }
            }
        }

        上述代码,只要是奇数就会出现除0的错误,直接运行打印如下:

         可见运行了多个线程,并出现了多个除0错误。但是我发现这次的错误异常抛出,如果是打印 InnerException 的话,可能会收集不完整,显示不出堆栈信息。但是这个其实也能接受,毕竟只要知道一个错误就行,对于多线程来说都是一样的,并不用在意同一个错误出现了几次。


(未完待续)

 本教程对应学习工程:魔术师Dix / HandsOnParallelProgramming · GitCode        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/727803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Xshell连接不上虚拟机的解决办法(给他最后一次机会)

VM还原默认设置 如果你之前的操作都没问题的话Xshell还是连接不上我们的虚拟机,可以试试这个方法 点VM中的 编辑–>虚拟网络编辑器–还原默认设置**(这个方法也特别有效)** 注意还原好以后我们主要看一下VM8的 这是没还原之前的NAT设置 没还原之前的DHCP设置…

如何在Windows 10中创建引导到UEFI固件设置的快捷方式

大多数计算机都有一个特定的键,当计算机启动时按下该键,用户可以访问UEFI(固件)设置。然而,我们经常在错过给定的时间段时按键太晚,因为笔记本电脑默认情况下只需等待几秒钟就可以启动到 Windows。 另一个引导到 UEFI 设置的选项是重新启动到高级启动选项,然后从那里开…

centos6.X防火墙110.42.2

防火墙机制介绍122.228.84 Centos5.X 6.X的防火墙机制为什么称为iptables呢? 因为这个防火墙软件里面有多个表格(table),每个表格都定义自己的默认策略与规则,且每个表用途都不同。 Centos5.X 6.X 主要表格(table&am…

第三课:设计小技巧

前期准备 下载一份官方规范,将官方规范文件置入到 Figma 中,若是使用网页版,建议打开两个 Figma 网页,在两个网页中分别打开规范文档和需要设计的项目,这样便可以通过 Tab 切换,快速将官方文档中的文件复…

学习c++ Part03

文章目录 前言1.动态空间申请1.1 静态空间申请1.2 动态分配 2.字符串处理函数3.结构体3.1 结构体的浅拷贝3.2 结构体的深拷贝3.3 结构体变量在堆区 结构体指针成员也指向堆区(先释放成员,再释放结构体)3.4 结构体的对齐规则3.5 结构体的位域&…

跟我一起从零开始学python(三)多线程/多进程/协程

前言 回顾之前讲了python语法编程 ,关于从零入门python的第一遍,编程语法必修内容,比如python3基础入门,列表与元组,字符串,字典,条件丶循环和其他语句丶函数丶面向对象丶异常和文件处理和网络…

oracle,update更新时,条件没走索引

update更新时没走索引, 查询索引是有效的: 没走索引的原因是条件字段的字段类型不一致, 一个是varchar2, 另一个是 nvarchar2 。 要走索引需要字段类型一致,可以利用to_char()将 nvarchar2转为 varchar2

VS2019+Qt5.15 在线显示百度地图

1.Qt5.15编译程序需要选择mscv2019 Release版本 2.需要到百度地图开发平台注册并获取到开发者key 3.显示地图是JS与Qt的交互过程&#xff0c;显示地图的html文件&#xff1a; <!DOCTYPE html> <html><head> <meta name"viewport" content&q…

订单自动取消的11种实现方式(上)

一、DelayQueue DelayQueue是JDK提供的api&#xff0c;是一个延迟队列 DelayQueue泛型参数得实现Delayed接口&#xff0c;Delayed继承了Comparable接口。 getDelay方法返回这个任务还剩多久时间可以执行&#xff0c;小于0的时候说明可以这个延迟任务到了执行的时间了。 com…

企业微信小程序登录,错误码:60020

在使用企业微信wx.qy.login API进行登录获取【session_key】时&#xff0c;报出错误码&#xff1a;60020 此错误记得好像意指的是获取的企业【access_token】用以去置换登录令牌【session_key】时&#xff0c;下发【access_token】的IP地址和获取【session_key】的IP不一致&am…

kotlin Flow系列之 - 冷流SafeFlow源码解析之 - Safe在那里?

本文涉及源码基于kotlinx-coroutines-core-jvm:1.7.1 kotlin 协成系列文章: 你真的了解kotlin中协程的suspendCoroutine原理吗? Kotlin Channel系列&#xff08;一&#xff09;之读懂Channel每一行源码 kotlin Flow系列之-冷流SafeFlow源码解析之 - Safe在那里&#xff1f; ko…

【vue2动画效果】实现两组单词逐渐减短,最后只保留首字母的效果

前言 实现两组单词逐渐减短&#xff0c;最后只保留首字母的效果 效果&#xff1a; 正文 <template><div class"header"><div style"margin-right: 12px; display: inline-flex"><divclass"door"id"book1"v-f…

常用数据回归建模算法总结记录

本文的主要目的是总结记录日常学习工作中常用到的一些数据回归拟合算法&#xff0c;对其原理简单总结记录&#xff0c;同时分析对应的优缺点&#xff0c;以后需要的时候可以直接翻看&#xff0c;避免每次都要查询浪费时间&#xff0c;欢迎补充。 (1)线性回归 (Linear Regressio…

解决springboot上传中文文件报错:NoClassDefFoundError: javax/mail/internet/MimeUtility

解决springboot上传中文文件报错:NoClassDefFoundError: javax/mail/internet/MimeUtility 1. 背景&#xff1a; springboot版本&#xff1a;2.7.11 前端使用 UnityEngine.WWWForm 进行文件上传 报错信息&#xff1a;org.springframework.web.multipart.MultipartException: F…

【资料分享】RK3568开发板规格书(4x ARM Cortex-A55(64bit),主频1.8GHz)

1 开发板简介 创龙科技TL3568-EVM是一款基于瑞芯微RK3568J/RK3568B2处理器设计的四核ARM Cortex-A55国产工业评估板&#xff0c;每核主频高达1.8GHz/2.0GHz&#xff0c;由核心板和评估底板组成。核心板CPU、ROM、RAM、电源、晶振、连接器等所有器件均采用国产工业级方案&#…

【拼多多API商品详情页面采集】具体的API接口调用步骤

要从拼多多获取商品数据&#xff0c;可以使用拼多多提供的API接口。首先需要注册一个拼多多开放平台的开发者账号&#xff0c;然后创建一个应用程序&#xff0c;获取应用程序的app_id和app_secret&#xff0c;以在API请求中进行身份验证。 在使用API接口时&#xff0c;需要按照…

力扣1816. 截断句子

代码展示&#xff1a; 方法1&#xff1a;通过StringBuilder创建的变量str来记录截断得到的字符串 思路&#xff1a;遍历字符串s&#xff0c;定义一个变量count_space来记录空格出现的次数&#xff0c;当空格没有出现k次时便将字符依次连接到StringBuilder类型的变量str后&#…

Web跳转案例、表单案例

一、跳转案例 <img>&#xff1a;html元素将图像嵌入文档 <body> <img src"../images(1)/images/7.5-1.jpg"> </body> 使用a标签进行一个跳转链接 <!DOCTYPE html> <html lang"en"> <head> <meta charset&qu…

7-3学习发布订阅模式,观察者模式

7-3学习发布订阅模式&#xff0c;观察者模式 1.发布订阅模式2.观察者模式 1.发布订阅模式 前端比较重要的两个设计模式&#xff0c;发布订阅模式和观察者模式。来简单的学习下。 let fs require(fs); let person {}let event {arr:[],on(fn){this.arr.push(fn);},emit(){t…

谷歌浏览器如何实现书签同步

推荐使用GIT仓库来当做中间介质&#xff0c;实现书签上传和下载&#xff0c;可以在不同机器上的谷歌浏览器之间同步书签 这里默认已经有了Git和谷歌浏览器&#xff0c;其中谷歌浏览器可以登陆账号也可以不登录。 GIT上创建私密仓库用于存储书签的json文件&#xff0c;生成秘钥…