.Net并行处理之Parallel类

本文深入解析了.NET Framework中Parallel类的功能,包括Parallel.For、Parallel.ForEach和Parallel.Invoke方法的使用,以及ParallelLoopResult返回结果的解读。文章通过代码示例展示了如何利用这些方法实现数据和任务的并行处理,特别关注于中断迭代和取消并行任务的机制。

0x00 介绍

Parallel类是对线程的抽象,提供数据与任务的并行性。类定义了静态方法For和ForEach,使用多个任务来完成多个作业。Parallel.For和Parallel.ForEach方法在每次迭代的时候调用相同的代码,而Parallel.Invoke()方法允许同时调用不同的方法。Parallel.ForEach()方法用于数据的并行性,Parallel.Invoke()方法用于任务的并行性。

以下内容只针对我在项目中使用到的情况进行记录,当然还有更多的重载和实现没有讲解出来。

0x01 命名空间

Parallel 所在的命名空间是 System.Threading.Tasks,看名字就知道与线程,任务有关。
使用时 using System.Threading.Tasks;即可使用Parallel类的方法

0x02 并行方法

Parallel对象提供了3种方法来实现 数据和任务的并行

  • Parallel.For
  • Parallel.ForEach
  • Parallel.Invoke

0x03 并行返回结果 ParallelLoopResult

ParallelLoopResult 提供了以下两个属性

        //
        // 摘要:
        //     获取该循环是否已运行完成(即,该循环的所有迭代均已执行,并且该循环没有收到提前结束的请求)。
        //
        // 返回结果:
        //     如果该循环已运行完成,则为 true;否则为 false。
        public bool IsCompleted { get; }
        //
        // 摘要:
        //     获取从中调用 System.Threading.Tasks.ParallelLoopState.Break 的最低迭代的索引。
        //
        // 返回结果:
        //     返回一个表示从中调用 Break 语句的最低迭代的整数。
        public long? LowestBreakIteration { get; }
  • IsCompleted
    并行任务执行的过程是否完整的执行完毕,中途未通过Break()方法来中断,如果使用Break中断则返回false
  • LowestBreakIteration
    返回当前并行任务执行过程种Break()所在的迭代索引。

0x04 Parallel.For

通过下面代码我们来了解下 Parallel.For 的运行方式,
第一个参数是迭代开始的值,
第二个参数是迭代结束的值,
第三个参数是 一个委托方法该方法有两种比较常用的重载

  • 第一种重载方法 (i)=>{}
            ParallelLoopResult result = Parallel.For(0, 10, (i) =>
            {
                Console.WriteLine("Task: count={0},id={1},threadid={2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
                //your business code
                Thread.Sleep(1000);
            });

            //result 查看返回的状态
            Console.WriteLine("Is Break = {0}", !result.IsCompleted);
            Console.WriteLine("Break Index = {0}", result.LowestBreakIteration);

运行结果
在这里插入图片描述

  • 第二种重载方法 (i,state)=>{}
            ParallelLoopResult result = Parallel.For(0, 10, (i,state) =>
            {
                Console.WriteLine("Task: count={0},id={1},threadid={2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
                //your business code
                state.Break();
                Thread.Sleep(1000);
            });

            //result 查看返回的状态
            Console.WriteLine("Is Break = {0}", !result.IsCompleted);
            Console.WriteLine("Break Index = {0}", result.LowestBreakIteration);

运行结果
在这里插入图片描述

再结果中 我们看到 第二种方式 我们使用了 state.Break();来中断了迭代,
在返回结果中IsCompleted返回的是false,LowestBreakIteration返回了0
但是在任务里却执行了两次任务,说明 Break()方法并不能中断已经提交的并行任务。

0x05 Parallel.ForEach

Parallel.ForEach的运行原理跟For相似,只是参数不同
第一个参数是集合对象
第二个参数是一个委托方法该方法有三种比较常用的重载

  • 第一种重载方法(v)=>{}
            String[] Items = new String[] { "A", "B", "C", "D", "E", "F", "G" };
            
            ParallelLoopResult result = Parallel.ForEach(Items,value =>
            {
                Console.WriteLine("Task: value={0},id={1},threadid={2}", value, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
                //your business code
                //state.Break();
                Thread.Sleep(1000);
            });

            //result 查看返回的状态
            Console.WriteLine("Is Break = {0}", !result.IsCompleted);
            Console.WriteLine("Break Index = {0}", result.LowestBreakIteration);

运行结果
在这里插入图片描述

  • 第二种重载方法 (v,state)=>{}
          String[] Items = new String[] { "A", "B", "C", "D", "E", "F", "G" };
            
            ParallelLoopResult result = Parallel.ForEach(Items,(value, state) =>
            {
                Console.WriteLine("Task: value={0},id={1},threadid={2}", value, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
                //your business code
               // state.Break();
                Thread.Sleep(1000);
            });

            //result 查看返回的状态
            Console.WriteLine("Is Break = {0}", !result.IsCompleted);
            Console.WriteLine("Break Index = {0}", result.LowestBreakIteration);

运行结果
在这里插入图片描述

  • 第三种重载方法 (v,state,i)=>{}

            String[] Items = new String[] { "A", "B", "C", "D", "E", "F", "G" };
            
            ParallelLoopResult result = Parallel.ForEach(Items,(value, state,i) =>
            {
                Console.WriteLine("Task: value={0},id={1},threadid={2},count={3}", value, Task.CurrentId, Thread.CurrentThread.ManagedThreadId,i);
                //your business code
                state.Break();
                Thread.Sleep(1000);
            });

            //result 查看返回的状态
            Console.WriteLine("Is Break = {0}", !result.IsCompleted);
            Console.WriteLine("Break Index = {0}", result.LowestBreakIteration);

运行结果
在这里插入图片描述

0x06 Parallel.Invoke

Parallel.Invoke属于方法级别的并行
它的参数params Action[] actions
ParallelOptions parallelOptions, params Action[] actions 两种重载方法
其中 ParallelOptions 提供了取消并行任务的信号

            ParallelOptions parallelOptions = new ParallelOptions();
            CancellationTokenSource tokenSource = new CancellationTokenSource();
            //最大允许10个任务并行
            parallelOptions.MaxDegreeOfParallelism = 10;
            //取消并行的信号
            parallelOptions.CancellationToken = tokenSource.Token;
            //你可以在并行任务的过程中调用Cancel方法取消并行任务
            //tokenSource.Cancel();

            Action[] actions = new Action[]
            {() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("taks1....");
            },
            () =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("task2.....");
            }};
            Parallel.Invoke(actions.ToArray());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值