并行的扩展

扩展1.

Parallel的使用:

在Parallel下面有三个常用的方法Invoke,For,ForEach

Parallel.Invoke()方法是最简单,最简洁的将串行的代码并行化.

在这里先说一点,就是Stopwatch的使用,Stopwatch到底是个什么东西,首先Stopwatch在命名空间System.Diagnostics中.

使用方法如下:

var StopWatch =new Stopwatch();//创建一个Stopwatch实例

StopWatch.Start();//开始计时

StopWatch.Stop();//停止计时

StopWatch.Reset();//重置StopWatch

StopWatch.Restart();//重启被停止的Stopwatch

stopWatch.ElapsedMilliseconds //获取stopWatch从开始到现在的时间差,单位是毫秒

案例:

using System;

using System.Collections.Concurrent;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Text;

using System.Threading;

using System.Threading.Tasks;

namespace 并行集合和LINQ

{

class Program

{

static void Main(string[] args)

{

Custom custom = new Custom();

custom.ParallelInvokeMethod();

Console.WriteLine("运行完成");

Console.ReadKey();

}

}

public class Custom

{

private Stopwatch stopWatch = new Stopwatch();

public void Run1()

{

Thread.Sleep(2000);//Thread需要添加命名空间

Console.WriteLine("Task 1 is cost 2 sec");

}

public void Run2()

{

Thread.Sleep(3000);

Console.WriteLine("Task 2 is cost 3 sec");

}

public void ParallelInvokeMethod()

{

stopWatch.Start();

Parallel.Invoke(Run1, Run2);

stopWatch.Stop();

Console.WriteLine("Parallel run " + stopWatch.ElapsedMilliseconds + " ms.");//这是在并行的情况下

stopWatch.Restart();

Run1();

Run2();

stopWatch.Stop();

Console.WriteLine("Normal run " + stopWatch.ElapsedMilliseconds + " ms.");//这是正常情况

}

}

}

分析:正确情况下确实应该是5秒左右,明明白白写着呢,3000+2000=5000ms,而使用了Parallel.Invoke方法只用了3秒,由此可见并行执行提高了很多效率.

扩展2:Parallel.For

这个方法和For循环的功能类似,案例:

using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace 并行扩展

{

class Program

{

static void Main(string[] args)

{

Stopwatch stopWatch = new Stopwatch();

stopWatch.Start();

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

{

for (int j = 0; j < 60000; j++)

{

int sum = 0;

sum += i;

}

}

stopWatch.Stop();

Console.WriteLine("NormalFor run " + stopWatch.ElapsedMilliseconds + " ms.");

stopWatch.Reset();

stopWatch.Start();

Parallel.For(0, 10000, item =>

{

for (int j = 0; j < 60000; j++)

{

int sum = 0;

sum += item;

}

});

stopWatch.Stop();

Console.WriteLine("ParallelFor run " + stopWatch.ElapsedMilliseconds + " ms.");

Console.WriteLine("运行完毕");

Console.ReadKey();

}

}

}

分析:写了两个循环,做些无用的操作,主要是消耗CPU的资源,通过多次运行结果可以看到们使用了Parallel.For所有的时间差不多也就是单纯for时间的三分之一.是不是在任何时候Parallel.For在任何时候都比这普通的for快呢,肯定不是啊,要是这样的话,C#的for早就淘汰了.

案例:修改代码,添加一个全局变量num

using System;

using System.Collections.Concurrent;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace 并行扩展

{

class Program

{

static void Main(string[] args)

{

Stopwatch stopWatch = new Stopwatch();

var obj = new Object();

long num = 0;

ConcurrentBag<long> bag = new ConcurrentBag<long>();

stopWatch.Start();

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

{

for (int j = 0; j < 60000; j++)

{

//int sum = 0;

//sum += item;

num++;

}

}

stopWatch.Stop();

Console.WriteLine("NormalFor run " + stopWatch.ElapsedMilliseconds + " ms.");

stopWatch.Reset();

stopWatch.Start();

Parallel.For(0, 10000, item =>

{

for (int j = 0; j < 60000; j++)

{

//int sum = 0;

//sum += item;

lock (obj)

{

num++;

}

}

});

stopWatch.Stop();

Console.WriteLine("ParallelFor run " + stopWatch.ElapsedMilliseconds + " ms.");

//并行的问题,需要多运行几遍,一遍两遍看不出什么东西来

Console.WriteLine("运行完毕");

Console.ReadKey();

}

}

}

分析:Parallel.For由于是并行运行的,所以会同时访问访问全局变量num,为了得到正确的结果,要使用lock,所以Parallel.For竟然耗了这么多时间,这是因为并行同时访问全局变量,会出现资源争夺(我的电脑当时开着虚拟机,听着音乐,在程序运行的时候我我Ctrl+S了以下文档,我的电脑出现卡死的情况),大不多的资源都消耗在了资源等待上面.

虽然一直说并说,但一直没有证明一下,你肯定不服,来让你服气:

Parallel.For(0, 100, i =>

{

Console.Write(i + "\t");

});

Console.WriteLine("运行完毕");

从0输出到99,运行后会发现输出的顺序不对,用for顺序肯定是对的,并行同时执行,所以会出现输出顺序不同的情况。

扩展3

Parallel.ForEach

这个方法和普通的foreach很相似,案例:

List<int> list = new List<int>();

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

{

list.Add(i);

}

Stopwatch stopWatch = new Stopwatch();

stopWatch.Start();

Parallel.ForEach(list, i =>

{

i++;

});

stopWatch.Stop();

Console.WriteLine(stopWatch.ElapsedMilliseconds);

Parallel中途退出循环和异常处理

我们为啥使用Parallel呢,肯定是在处理一些比较好使的任务,当然也很消耗CPU资源和内存,如果我们在中途想停止,怎么办呢?

串行好办啊,一个break搞定,但是串行呢?貌似不知道呢,在并行循环的委托参数中提供了一个ParallelLoopState,该实例提供了Break和Stop方法来帮助我们!

Break: 当然这个是通知并行计算尽快的退出循环,比如并行计算正在迭代100,那么break后程序还会迭代所有小于100的。

Stop:这个就不一样了,比如正在迭代100突然遇到stop,那它啥也不管了,直接退出。

案例:

Stopwatch stopWatch = new Stopwatch();

ConcurrentBag<int> bag = new ConcurrentBag<int>();

stopWatch.Start();

Parallel.For(0, 1000, (i, state) =>

{

if (bag.Count == 300)

{

//state.Stop();//也可能会出现300多,但是不会很夸张,在我的测试下,最多出现303,大部分还是300

state.Break();//如果是break的话,可能会看到Bag count is 300(多),在我多次测试下,得到最夸张的结果是840

return;

}

bag.Add(i);

});

stopWatch.Stop();

Console.WriteLine("Bag count is " + bag.Count + ", " + "一共用时 :"+stopWatch.ElapsedMilliseconds+"ms");

Console.WriteLine("运行完毕");

Console.ReadKey();

异常:

首先任务是并行计算的,处理过程中可能会产生n多的异常,那么如何来获取到这些异常呢?普通的Exception并不能获取到异常,然而为并行诞生的AggregateExcepation就可以获取到一组异常。

这里我们修改Parallel.Invoke的代码,修改后代码如下:

private Stopwatch stopWatch = new Stopwatch();

public void Run1()

{

Thread.Sleep(2000);

Console.WriteLine("Task 1 is cost 2 sec");

throw new Exception("Exception in task 1");

}

public void Run2()

{

Thread.Sleep(3000);

Console.WriteLine("Task 2 is cost 3 sec");

throw new Exception("Exception in task 2");

}

public void ParallelInvokeMethod()

{

stopWatch.Start();

try

{

Parallel.Invoke(Run1, Run2);

}

catch (AggregateException aex)

{

foreach (var ex in aex.InnerExceptions)

{

Console.WriteLine(ex.Message);

}

}

stopWatch.Stop();

Console.WriteLine("Parallel run " + stopWatch.ElapsedMilliseconds + " ms.");

stopWatch.Reset();

stopWatch.Start();

try

{

Run1();

Run2();

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

stopWatch.Stop();

Console.WriteLine("Normal run " + stopWatch.ElapsedMilliseconds + " ms.");

Console.WriteLine("运行完毕");

Console.ReadKey();

C#编程(六十四)----------并行扩展的更多相关文章

  1. Gradle 1.12用户指南翻译——第六十四章. 发布到Ivy(新)

    其他章节的翻译请参见:http://blog.csdn.net/column/details/gradle-translation.html翻译项目请关注Github上的地址:https://gith ...

  2. 孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3

    孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十天. 今天继续学习mongoDB的简单操作, ...

  3. SpringBoot进阶教程(六十四)注解大全

    在Spring1.x时代,还没出现注解,需要大量xml配置文件并在内部编写大量bean标签.Java5推出新特性annotation,为spring的更新奠定了基础.从Spring 2.X开始spri ...

  4. 第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理

    第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理 1.映射(mapping)介绍 映射:创建索引的时候,可以预先定义字 ...

  5. “全栈2019”Java第六十四章:接口与静态方法详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. 学习ASP.NET Core Razor 编程系列十四——文件上传功能(二)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  7. OpenCV开发笔记(六十四):红胖子8分钟带你深入了解SURF特征点(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  8. C#高级编程六十九天----DLR简介 .在.NET中使用DLR(转载) 我也来说说Dynamic

    DLR 一.近年来,在TIOBE公司每个月发布的编程语言排行榜中,C#总是能挤进前十名,而在最近十年来,C#总体上呈现上升的趋势.C#能取得这样的成绩,有很多因素,其中它在语言特性上的锐意进取让人印象 ...

  9. 第六十四天 JS基础操作

    一.分支结构 1.if语句 if基础语句 if(条件表达式){ 代码块: } // 当条件表达式结果为true,会执行代码块:反之不执行 // 条件表达式可以为普通表达式 // 0.undefined ...

随机推荐

  1. 三、vue脚手架工具vue-cli的使用

    1.vue-cli构建 vue-cli工具构建:https://blog.csdn.net/u013182762/article/details/53021374 npm的镜像替换成淘宝 2.项目运行 ...

  2. 从零开始自己搭建复杂网络(以Tensorflow为例)

    从零开始自己搭建复杂网络(以MobileNetV2为例) tensorflow经过这几年的发展,已经成长为最大的神经网络框架.而mobileNetV2在经过Xception的实践与深度可分离卷积的应用 ...

  3. MCS-51 单片机的中断系统

    MCS-51 单片机的中断系统 MCS-51中断系统:5个中断源(两个外部中断, 两个定时器, 一个串口),2个优先级 中断相关概念 中断:当CPU正在处理某件事情时,单片机外部或内部发生的某一紧急事 ...

  4. NOIp 2018 提高组

    T1铺设道路 传送门 题目描述 春春是一名道路工程师,负责铺设一条长度为 $ n $ 的道路. 铺设道路的主要工作是填平下陷的地表.整段道路可以看作是 $ n $ 块首尾相连的区域,一开始,第 ii ...

  5. 当父级绑定了DataContext之内的数据源时,子级想重新绑回DataContext

    <Grid x:Name="NewDeploymentObjectPanel" Background="White" DataContext=" ...

  6. 如何批量删除word文档中的超级链接?

    有时候从网页上copy来的文章中,会带有非常多的链接,这些链接很烦人是吧?如何批量删除(一次性全部删除)word文章中的超链接呢? 有些朋友说,Ctrl+A全选文章,然后点击格式工具栏上的“清除格式” ...

  7. 《Look Mom, I don’t use Shellcode》议题解析

    0x0 前言 <Look Mom, I don’t use Shellcode>是2016年Syscan360上讲过的一个议题,这个议题的副标题是"Browser Exploit ...

  8. 《高性能MySQL》学习笔记

    第1章 MySQL架构与历史 1.2 并发控制 MySQL在两个层面实现并发控制:服务器层与存储引擎层. 读锁和写锁: 在处理并发读或写时,可以通过实现一个由两种锁组成的系统来解决问题. 这两种锁通常 ...

  9. jquery.validate.js自定义表单验证

    $(document).ready(function() { //在下列位置输入页面加载的逻辑代码 $("#inputForm").validate({ rules: { seq: ...

  10. js冲刺一下

    js中__proto__和prototype的区别和关系 1.对象有属性__proto__,指向该对象的构造函数的原型对象. 2.方法除了有属性__proto__,还有属性prototype,prot ...