Parallel 类提供对并行循环和区域的支持。

许多个人计算机和工作站都有两个或四个内核(即 CPU),使多个线程能够同时执行。 在不久的将来,计算机预期会有更多的内核。 为了利用当今和未来的硬件,您可以对代码进行并行化,以将工作分摊在多个处理器上。 过去,并行化需要线程和锁的低级操作。 Visual Studio 2010 和 .NET Framework 4 提供了新的运行时、新的类库类型以及新的诊断工具,从而增强了对并行编程的支持。 这些功能简化了并行开发,使您能够通过固有方法编写高效、细化且可伸缩的并行代码,而不必直接处理线程或线程池。 下图从较高层面上概述了 .NET Framework 4 中的并行编程体系结构。

上面是MSDN对于并行任务的解释,简而言之就是同时执行多个任务,带来效率上的提高,但是同时带来CPU占用;

1.简单Parallel.For/Parallel.ForEach循环

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
 
namespace ConsoleApplication17
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                NormalFor();
                ParallelFor();
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("Exception Message:{0}", ex.Message.Trim()));
            }
            finally
            {
                Console.ReadLine();
            }
        }
        static int _forCount = 100;
        static void NormalFor()
        {
            Stopwatch _watch = new Stopwatch();
            _watch.Start();
            for (int i = 0; i < _forCount; i++)
            {
                DoSomeWork(i);
            }
            _watch.Stop();
            Console.WriteLine(string.Format("Normal For Cost Time:{0}", _watch.ElapsedMilliseconds));
        }
        static void ParallelFor()
        {
            Stopwatch _watch = new Stopwatch();
            _watch.Start();
            //写法一
            Parallel.For(0, _forCount, i =>
            {
                DoSomeWork(i);
            });
            _watch.Stop();
            Console.WriteLine(string.Format("Parallel For Cost Time:{0}", _watch.ElapsedMilliseconds));
            /*
            Parallel.For(0, _forCount, DoSomeWork);//写法二
            Parallel.For(0, _forCount, (int i) => { DoSomeWork(i); });//写法三
            */
        }
        static void DoSomeWork(int i)
        {
            if (i < 0)
                throw new ArgumentException("i");
            Thread.Sleep(100);
        }
    }
}

代码效果

2.停止或中断 Parallel.For 循环

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
 
namespace ConsoleApplication17
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                BreakParallelFor();
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("Exception Message:{0}", ex.Message.Trim()));
            }
            finally
            {
                Console.ReadLine();
            }
        }
        static int _forCount = 100;
        static void BreakParallelFor()
        {
            Parallel.For(0, _forCount, (i, status) =>
            {
                if (i == 22)
                {
                    Console.WriteLine("Parallel For Break....");
                    status.Break();
                }
                Console.WriteLine(string.Format("output :{0}", i));
                Thread.Sleep(100);
            });
        }
    }
}

代码效果

看看MSDN关于此的解释:

在 ParallelFor() 或 [Overload:System.Threading.Tasks.Parallel.Parallel.ForEach`1] 循环中,不能使用与顺序循环中相同的 break 或 Exit 语句,这是因为这些语言构造对于循环是有效的,而并行“循环”实际上是方法,不是循环。 相反,可以使用 Stop 或 Break 方法。 Parallel.For的一些重载接受 Action<int, ParallelLoopState>(在 Visual Basic 中为 Action(Of Integer, ParallelLoopState))作为输入参数。 ParallelLoopState 对象由运行时在后台创建,您可以在 lambda 表达式中为它指定您喜欢的任何名称。

在调用 Stop 或 Break 后,循环中的其他线程可能会继续运行一段时间(这不受应用程序开发人员的控制),理解这一点很重要。 可以使用 ParallelLoopState.IsStopped 属性检查是否已在另一个线程上停止该循环。

理解黄色标注地方很重要;

3.具有线程局部变量的 Parallel.ForEach Parallel.For 循环(代码很乱未调!)

  1. using System;
  2. using System.Linq;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. namespace ConsoleApplication17{
  6. class Program    {
  7. static void Main(string[] args)           {
  8. try
  9. {                //例子参考自MSDN:http://msdn.microsoft.com/zh-cn/library/dd460703%28v=vs.100%29.aspx
  10. int[] _nums = Enumerable.Range(0, 10).ToArray();
  11. long _fortotal = 0, _foreahtotal = 0;
  12. Parallel.For<long>(0, _nums.Length,                    () => 0,//每次遍历开始时候初始化变量 类似于 int _subSum=0;
  13. (i, loopStatus, eachLoopTotal) =>//i:循环的索引;loopstatus:并行遍历状态;eachLoopTotal:每次遍历累加小计值
  14. {
  15. eachLoopTotal += _nums[i];
  16. return eachLoopTotal;
  17. },
  18. (eachLoopTotal) =>//遍历结束时候,将上面每次累加小计数值传递过来,进行总的累加
  19. {                        Interlocked.Add(ref _fortotal, eachLoopTotal);
  20. });                /*
  21. localInit
  22. 类型:System.Func<TLocal>
  23. 用于返回每个线程的本地数据的初始状态的函数委托。
  24. body
  25. 类型:System.Func<Int64, ParallelLoopState, TLocal, TLocal>
  26. 将为每个迭代调用一次的委托。
  27. localFinally
  28. 类型:System.Action<TLocal>
  29. 用于对每个线程的本地状态执行一个最终操作的委托。
  30. */
  31. Parallel.ForEach<int, long>(_nums,
  32. () => 0,
  33. (i, loopStatus, eachLoopTotal) =>
  34. {
  35. eachLoopTotal += _nums[i];
  36. return eachLoopTotal;
  37. },
  38. (eachLoopTotal) =>
  39. {
  40. Interlocked.Add(ref _foreahtotal, eachLoopTotal);
  41. });
  42. Console.WriteLine("The Parallel.For is {0}", _fortotal);
  43. Console.WriteLine("The Parallel.ForEach is {0}", _foreahtotal);
  44. }            catch (Exception ex)
  45. {
  46. Console.WriteLine(string.Format("Exception Message:{0}", ex.Message.Trim()));
  47. }
  48. finally
  49. {
  50. Console.ReadLine();
  51. }
  52. }
  53. }}
  54. }
  55. }
  56. }
 

代码效果

4.取消 Parallel.For/ForEach Loop

using System;
using System.Threading;
using System.Threading.Tasks;
 
namespace ConsoleApplication17
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                /*
                 CancellationToken 获取或设置与此 ParallelOptions 实例关联的 CancellationToken。 
                 MaxDegreeOfParallelism 获取或设置此 ParallelOptions 实例所允许的最大并行度。 
                 TaskScheduler 获取或设置与此 ParallelOptions 实例关联的 TaskScheduler。 将此属性设置为 null,以指示应使用当前计划程序。
                 MaxDegreeOfParallelism MaxDegreeOfParallelism设置为2,表示最多可以有2个并行量(可以理解成并行线程数目),如果设置为为 -1,表示对于应该使用的并行量没有上限设置。如果将其设置为1,则效果和单线程一样.
                 */
                CancellationTokenSource _cancel = new CancellationTokenSource();
                ParallelOptions _po = new ParallelOptions();
                _po.CancellationToken = _cancel.Token;
                _po.MaxDegreeOfParallelism = Environment.ProcessorCount;
 
                Parallel.For(0, 100, _po, i =>
                    {
                        if (i == 22)
                            _cancel.Cancel();
                        Console.WriteLine(string.Format("output {0}", i));
                    });
            }
            catch (OperationCanceledException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("Exception Message:{0}", ex.Message.Trim()));
            }
            finally
            {
                Console.ReadLine();
            }
        }
    }
}

代码效果

.Net(C#)Parallel"循环"的解释以及与循环的比较的更多相关文章

  1. [Effective JavaScript 笔记]第49条:数组迭代要优先使用for循环而不是for...in循环

    示例 下面代码中mean的输出值是多少? var scores=[98,74,85,77,93,100,89]; var total=0; for(var score in scores){ tota ...

  2. JS中for循环变量作用域--解决for循环异步执行的问题

    被这个问题困惑了很久,终于在网上找到了答案,感谢~ 现在分享给大家~ js中如何让一个for循环走完之后,再去执行下面的语句? 这涉及for循环变量作用域的问题,js中作用域只有函数作用域和全局作用域 ...

  3. 不可在 for 循环体内修改循环变量,防止 for 循环失去控制

    不可在 for 循环体内修改循环变量,防止 for 循环失去控制. #include <iostream> /* run this program using the console pa ...

  4. java基础3 循环语句:While 循环语句、do while 循环语句、 for 循环语句 和 break、continue关键字

    一.While循环语句 1.格式 while(条件表达式){ 执行语句: } 2.要点 1,先判断后执行 2,循环次数不定 3,避免死循环 3.举例 题目1:输出0-100之间的所有数 class D ...

  5. python入门:CONTINUE 的作用 跳出本次循环后,重新开始循环

    #!/usr/bin/env python # -*- coding:utf-8 -*- # CONTINUE 的作用 跳出本次循环后,重新开始循环 import time while True: ' ...

  6. 流程控制,循环结构,for,while循环

    '''1.变量名命名规范 -- 1.只能由数字.字母 及 _ 组成 -- 2.不能以数字开头 -- 3.不能与系统关键字重名 -- 4._开头有特殊含义 -- 5.__开头__结尾的变量,魔法变量 - ...

  7. Shell基础(三):使用for循环结构、使用while循环结构、基于case分支编写脚本、使用Shell函数、中断及退出

    一.使用for循环结构 目标: 本案例要求编写一个Shell脚本chkhosts.sh,利用for循环来检测多个主机的存活状态,相关要求及说明如下: 1> 对192.168.4.0/24网段执行 ...

  8. if continue的用法(跳过本次循环,执行下一个循环)

    Python continue 语句跳出本次循环 当需要跳过本次循环的时候,使用continue能跳过本次循环,直接下一个循环 如下脚本: for url in alllink: if url == ...

  9. Java的三种循环:1、for循环 2、while循环 3、do...while循环

    Java的三种循环 Java三种循环结构: 1.for循环 2.while循环 3.do...while循环 循环结构组成部分:1.条件初始化语句,2.条件判断语句 , 3.循环体语句,4.条件控制语 ...

随机推荐

  1. 导出Excel offer2007以上

    package cn.knet.data.untils; import java.awt.Color; import java.io.File; import java.io.FileOutputSt ...

  2. 夺命雷公狗---DEDECMS----13dedecms首页的完成

    我们的dedecms搭建起来后直接复制templets的目录复制一份,如下所示: 然后进入templets目录里面,然后再将default里面的东西都给干掉,然后将我们预先准备好的首页放进来,代码如下 ...

  3. 关于windows操作系统的内核

    操作系统内核.从本质上来讲,它本身也是一个程序.比如windows的内核 ntoskrnl.exe 就是一个我们平常看到的 PE 文件,它的位置位于 \WINDOWS\system32\ntoskrn ...

  4. OpenGL中两种计算投影矩阵的函数

    OpenGL无意间同时看到两种创建投影矩阵的写法,可以说它们完成的是同样的功能,但写法完全不同,可以观摩一下什么叫做异曲同工之妙... 第一种: gltMakeShadowMatrix函数是重点 // ...

  5. Oracle 10g dataguard broker 配置

    环境: OS:rhel6.3_64bit DB:Oracle10gR2 ————————————————————————dataguard broker配置—————————————————————— ...

  6. COM编程之四 引用计数

    [1]客户为什么不应直接控制组件的生命期? 假设一个组件A正在使用另一个组件B,可想组件A(客户)代码中肯定有若干个指向组件B接口的指针. 那么这种情况下,当使用完一个接口而仍然在使用另一个接口时,是 ...

  7. linux设备驱动归纳总结(七):1.时间管理与内核延时【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-100005.html linux设备驱动归纳总结(七):1.时间管理与内核延时 xxxxxxxxxxx ...

  8. linux内核中异步通信机制--信号处理机制【转】

    转自:http://blog.csdn.net/lu_embedded/article/details/51131663 什么是异步通信?很简单,一旦设备准备好,就主动通知应用程序,这种情况下应用程序 ...

  9. 【Pro ASP.NET MVC 3 Framework】.学习笔记.11.ASP.NET MVC3的细节:概览MVC项目

    书Adam The Definitive Guide to HTML5 Adam Applied ASP.NET 4 in Context and Pro ASP.NET 4 到此为止,我们已经学了为 ...

  10. MySQL Replication的Reset slave重置命令

    有时要清除从库的所有复制信息,如切换为不同的Master, 主从重做等:Reset slave是一个比较危险的命令,所以在执行前一定要准备知道其含义. 1. 命令在slave上执行,执行前一定要停掉s ...