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

这篇具有很好参考价值的文章主要介绍了【C#】并行编程实战:使用 PLINQ(2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

         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 !");
                 });
        }

        打印结果如下:

【C#】并行编程实战:使用 PLINQ(2),学习总结,C#,多线程编程,c#,多线程编程,学习

         首先,这个执行是无序的;然后虽然每一次选择都有等待,但是每有一个 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 !");
            });
        }

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

【C#】并行编程实战:使用 PLINQ(2),学习总结,C#,多线程编程,c#,多线程编程,学习

         可以看到第一个结果出来等待了很久(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 !");
            });
        }

        打印结果如下:

【C#】并行编程实战:使用 PLINQ(2),学习总结,C#,多线程编程,c#,多线程编程,学习

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

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

PLINQ 中的合并选项 | Microsoft Learn详细了解:PLINQ 中的合并选项https://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的错误,直接运行打印如下:

【C#】并行编程实战:使用 PLINQ(2),学习总结,C#,多线程编程,c#,多线程编程,学习

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


(未完待续)

 本教程对应学习工程:魔术师Dix / HandsOnParallelProgramming · GitCode        文章来源地址https://www.toymoban.com/news/detail-541924.html

到了这里,关于【C#】并行编程实战:使用 PLINQ(2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C#】并行编程实战:序章

            本文主要是基于这本书学习的:         《并行编程实战:基于C#8和.NET Core 3》,我当时买的实体书,长下面这个样子。我买了大概浏览了一下,感觉内容还行(基本都是没见过的新东西),所以打算认真学一下。         配套的学习(原书)工程地址如下

    2024年02月08日
    浏览(84)
  • C++ 多线程之OpenMP并行编程使用详解

    总结OpenMP使用详解 本文转载自:https://blog.csdn.net/AAAA202012/article/details/123665617?spm=1001.2014.3001.5506   OpenMP(Open Multi-Processing)是一种用于共享内存并行系统的多线程程序设计方案, 支持的编程语言包括C、C++和Fortran。 OpenMP提供了对并行算法的高层抽象描述, 通过线程实现并行化

    2024年02月06日
    浏览(40)
  • unity的C#学习——多线程编程(线程的生命周期、创建与管理)与线程相关类

    多线程编程是 C# 一个比较难且涵盖面比较广的知识点,本文整理仓促而且属于笔记向博客,有些地方必然还存在不严谨和错误,本人会在日后的使用过程中不断完善。如果发现问题或有改进意见可以在评论区提出,我会及时修改。 线程是程序的执行流程,也被称为 轻量级进

    2024年02月12日
    浏览(44)
  • C#编程-在线程中使用同步

    在线程应用程序中,线程需要相互共享数据。但是,应用程序应该确保一个线程不更改另一个线程使用的数据。考虑有两个线程的场景。一个线程从文件读取工资,另一个线程尝试更新工资。当两个线程同时工作时,数据就会受损。下图显示了两个线程同时访问一个文件的数

    2024年01月16日
    浏览(39)
  • Python中的线程池与进程池:并行编程的高效选择【第145篇—并行编程】

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在Python编程中,实现并行处理任务是提高程序性能的关键。线程池和进程池是Python中常用的并行编程工具,它们能够有效地利用多核处理器的

    2024年04月08日
    浏览(73)
  • 学习系统编程No.32【线程互斥实战】

    北京时间:2023/7/19/15:22,昨天更新完博客,和舍友下了一会棋,快乐就是这么简单,哈哈哈!总体来说,摆烂程度得到一定的改善,想要达到以前的水准,需要一定的契机,毕竟人生在世,快乐最重要是吧!更文带给我的快乐已经没有那么多了,虽然欠了非常多的作业,非常

    2024年02月16日
    浏览(35)
  • 学习系统编程No.28【多线程概念实战】

    北京时间:2023/6/29/15:33,刚刚更新完博客,目前没什么状态,不好趁热打铁,需要去睡一会会,昨天睡的有点迟,然后忘记把7点到8点30之间的4个闹钟关掉了,恶心了我自己一早上,真的是罪过呀!极度没睡好加没睡够,由于上篇博客马上就可以完成,所以中午没有选择睡觉

    2024年02月16日
    浏览(33)
  • Java并发编程学习16-线程池的使用(中)

    上篇分析了在使用任务执行框架时需要注意的各种情况,并简单介绍了如何正确调整线程池大小。 本篇将继续介绍对线程池进行配置与调优的一些方法,详细如下: ThreadPoolExecutor 为 Executors 中的 newCachedThreadPool 、 newFixedThreadPool 和 newScheduledThreadExecutor 等工厂方法返回的 Exe

    2024年02月10日
    浏览(42)
  • Java并发编程学习18-线程池的使用(下)

    上篇介绍了 ThreadPoolExecutor 配置和扩展相关的信息,本篇开始将介绍递归算法的并行化。 还记得我们在《Java并发编程学习11-任务执行演示》中,对页面绘制程序进行一系列改进,这些改进大大地提供了页面绘制的并行性。 我们简单回顾下相关的改进过程: 第一次新增时,页

    2024年02月12日
    浏览(36)
  • C#编程-实现多线程

    多线程帮助同时执行各种操作。这为用户节省时间。多线程程序包括一个主线程和其他用户定义的线程以同时执行多个任务。 微处理器为执行的进程分配内存。每个进程占有内存中它们自己的地址空间。但是,所有在进程中的线程占有相同的地址空间。多线程允许在一个程序

    2024年02月02日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包