多核时代 .NET Framework 4 中的并行编程5---并行循环Parallel Loop

简介:

1. 并行循环与顺序循环区别

首先,来运行下面的代码,查看区别,代码如下:

static void Main(string[] args)

        {

            Console.WriteLine("使用For循环");

 

            for (int i = 0; i <= 10; i++)

            {

                Console.WriteLine("i = {0}, 线程id = {1}",

                    i, Thread.CurrentThread.ManagedThreadId);

                Thread.Sleep(10);

            }

 

            Console.WriteLine("使用Parallel.For");

 

            Parallel.For(0, 10, i =>

            {

                Console.WriteLine("i = {0}, 线程id = {1}", i,

                Thread.CurrentThread.ManagedThreadId);

                Thread.Sleep(10);

            });

 

            Console.ReadLine();

        }

最终运行的效果如下图所示:

 

从上面的代码运行效果图来我们可以看到,只有一个线程在处理for循环.而Parallel.For的循环,则会有多个线程进行处理,从而在某种程度改善了程序代码的运行效率.他们的区别就不言而喻.

2. Parallel的并行循环的几种方法

Parallel类提供以下几种并行执行循环的方法(他们还有很多其他的重载方法)。具体说明如下:

Ø Parallel.For:执行 for 循环,其中可能会并行运行迭代.

Ø Parallel.ForEach: 对某种集合中的对象执行 foreach,其中可能会并行运行迭代,需要主要的是,它不保证按照集合的索引顺序去执行迭代。

Ø Parallel.Invoke:尽可能并行执行提供的每个操作.

示例代码如下:

private static void Invoke()

        {

            Action[] actions = new Action[5];

            actions[0] = new Action(() =>

             {

                 Console.WriteLine("thread id={0}",Thread.CurrentThread.ManagedThreadId);

             });

            actions[1] = new Action(() =>

            {

                Console.WriteLine("thread id={0}",Thread.CurrentThread.ManagedThreadId);

            });

            actions[2] = new Action(() =>

            {

                Console.WriteLine("thread id={0}",Thread.CurrentThread.ManagedThreadId);

            });

            actions[3] = new Action(() =>

            {

                Console.WriteLine("thread id={0}",Thread.CurrentThread.ManagedThreadId);

            });

            actions[4] = new Action(() =>

            {

                Console.WriteLine("thread id={0}",Thread.CurrentThread.ManagedThreadId);

            });

 

            Parallel.Invoke(actions);

          

 

            List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6 };

 

            Parallel.ForEach(list, i =>

            {

                Console.WriteLine("i={0},thread id={1}", i,Thread.CurrentThread.ManagedThreadId);

            });

 

            Console.ReadLine();

        }

3. 返回值

ParallelLoopResult提供执行 Parallel 循环的完成状态。其中, ParallelLoopResult有两个属性:

Ø IsCompleted 获取该循环是否已运行完成(即,该循环的所有迭代均已执行,并且该循环没有收到提前结束的请求)。 

Ø LowestBreakIteration 获取从中调用 Break 的最低迭代的索引。

代码如下:

ParallelLoopResult loopResult = Parallel.ForEach(list, (int i,ParallelLoopState state) =>

             {

                 if (i == 5)

                 {

                     state.Break();

                 }

                 Console.WriteLine("i={0},thread id={1}", i,Thread.CurrentThread.ManagedThreadId);

             });

 

            Console.WriteLine("IsCompleted: {0}", loopResult.IsCompleted);

            Console.WriteLine("BreakValue: {0}", loopResult.LowestBreakIteration.HasValue);

            Console.ReadLine();

 

4. 控制循环

ParallelOptions类存储用于配置 Parallel 类的方法的操作的选项。其属性有:

Ø CancellationToken 获取或设置与此 ParallelOptions 实例关联的 CancellationToken。 

Ø MaxDegreeOfParallelism 获取或设置此 ParallelOptions 实例所允许的最大并行度。 

Ø TaskScheduler 获取或设置与此 ParallelOptions 实例关联的 TaskScheduler。 将此属性设置为 null,以指示应使用当前计划程序。

如下代码,通过设置CancellationToken以便可以取消Parallel的循环:

CancellationTokenSource token = new CancellationTokenSource();

            Task.Factory.StartNew(() =>

            {

                Thread.Sleep(5000);

                token.Cancel();

                Console.WriteLine("Token Cancelled.");

 

            });

            ParallelOptions loopOptions = new ParallelOptions()

            {

                CancellationToken = token.Token,

                MaxDegreeOfParallelism = 2

 

            };

            try

            {

               

                Parallel.For(0, Int64.MaxValue, loopOptions, i =>

                {

                  

                    Console.WriteLine("i={0},thread id={1}", i,Thread.CurrentThread.ManagedThreadId);

                    Thread.Sleep(1000);

                });

            }

            catch (OperationCanceledException)

            {

                Console.WriteLine("Exception...");

            }

其中, MaxDegreeOfParallelism设置为2,表示最多可以有2个并行量(可以理解成并行线程数目),如果设置为为 -1,表示对于应该使用的并行量没有上限设置。如果将其设置为1,则效果和单线程一样.

5. 停止/中断循环

通过调用ParallelLoopState实例的Stop方法和Break方法,可以停止和中断当前循环的执行.其中,

Ø Break 告知 Parallel 循环应在系统方便的时候尽早停止执行当前迭代之外的迭代.

Ø Stop 告知 Parallel 循环应在系统方便的时候尽早停止执行。

代码如下:

 Parallel.ForEach(list, (int i, ParallelLoopState state) =>

            {

                if (i == 5)

                {

                    state.Break();

                }

               

                Console.WriteLine("i={0},thread id={1}", i,Thread.CurrentThread.ManagedThreadId);

            });

其中, ParallelLoopState类的实例由Parallel类自动创建并传递到所执行的方法中.所以我们可以直接使用,而不是需要事前申明并实例一个ParallelLoopState对象.



    本文转自风车车  博客园博客,原文链接:http://www.cnblogs.com/xray2005/archive/2011/08/30/2159052.html,如需转载请自行联系原作者




相关文章
|
2月前
使用的是.NET Framework 4.0,并且需要使用SMTP协议发送电子邮件
使用的是.NET Framework 4.0,并且需要使用SMTP协议发送电子邮件
49 1
|
2月前
|
开发框架 缓存 监控
NET Framework 到 .NET 5/6 的迁移是重大的升级
本文详细介绍了从 .NET Framework 4.8 迁移到 .NET 5/6 的过程,通过具体案例分析了迁移策略与最佳实践,包括技术栈评估、代码迁移、依赖项更新及数据库访问层的调整,强调了分阶段迁移、保持代码可维护性及性能监控的重要性。
57 3
|
2月前
|
机器学习/深度学习 编解码 算法
【小样本图像分割-4】nnU-Net: Self-adapting Framework for U-Net-Based Medical Image Segmentation
《nnU-Net: 自适应框架用于基于U-Net的医学图像分割》是一篇2018年的论文,发表在Nature上。该研究提出了一种自适应的医学图像分割框架nnU-Net,能够自动调整模型的超参数以适应不同的数据集。通过2D和3D U-Net及级联U-Net的组合,nnU-Net在10个医学分割数据集上取得了卓越的性能,无需手动调整。该方法强调数据增强、预处理和训练策略等技巧,为医学图像分割提供了一个强大的解决方案。
81 0
【小样本图像分割-4】nnU-Net: Self-adapting Framework for U-Net-Based Medical Image Segmentation
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
本文讨论了在基于.NET 6和.NET Framework的WinForms项目中添加图表控件的不同方法。由于.NET 6的WinForms项目默认不包含Chart控件,可以通过NuGet包管理器安装如ScottPlot等图表插件。而对于基于.NET Framework的WinForms项目,Chart控件是默认存在的,也可以通过NuGet安装额外的图表插件,例如LiveCharts。文中提供了通过NuGet添加图表控件的步骤和截图说明。
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
NET Framework安装失败的麻烦
本人机子环境是安装了VS2012,即安装了 .NET Framework4.5,现在要安装AutoCAD2013,而安装CAD2013需要安装4.0的Framework,由于本机已有高版本的Framework,安装自然报错: 又不想来卸载4.5,觉得麻烦,但又想装上CAD2013,唯一的方法是修改Setup.ini初始化文件。
1065 0
|
3月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
44 7
|
3月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
71 0
|
4月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
53 0
|
4月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
4月前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
136 0