当前位置: 首页 > news >正文

[C#]Parallel使用

  随着多核时代的到来,并行开发越来越展示出它的强大威力!使用并行程序,充分的利用系统资源,提高程序的性能。在.net 4.0中,微软给我们提供了一个新的命名空间:System.Threading.Tasks。这里面有很多关于并行开发的东西,今天第一篇就介绍下最基础,最简单的——认识和使用Parallel。

一、 Parallel的使用

在Parallel下面有三个常用的方法invoke,For和ForEach。

1、Parallel.Invoke

这是最简单,最简洁的将串行的代码并行化。

在这里先讲一个知识点,就是StopWatch的使用,最近有一些人说找不到StopWatch,StopWatch到底是什么东西,今天就来说明一下。

StopWatch在System.Diagnostics命名控件,要使用它就要先引用这个命名空间。

其使用方法如下:

1

2

3

4

5

6

7

8

9

10

11

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

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

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

stopWatch.Reset();  //重置StopWatch

stopWatch.Restart(); //重新启动被停止的StopWatch

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

本次用到的就这么多知识点,想了解更多关于StopWatch的,去百度一下吧,网上有很多资料。

下面进入整体,开始介绍Parallel.Invoke方法,废话不多说了,首先新建一个控制台程序,添加一个类,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

public class ParallelDemo

 {

 private Stopwatch stopWatch = new Stopwatch();

 public void Run1()

 {

 Thread.Sleep(2000);

 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.");

 }

代码很简单,首先新加一个类,在类中写了两个方法,Run1和Run2,分别等待一定时间,输出一条信息,然后写了一个测试方法ParallelInvokeMethod,分别用两种方法调用Run1和Run2,然后在main方法中调用,下面来看一下运行时间如何:

  大家应该能够猜到,正常调用的话应该是5秒多,而Parallel.Invoke方法调用用了只有3秒,也就是耗时最长的那个方法,可以看出方法是并行执行的,执行效率提高了很多。

2、Parallel.For

这个方法和For循环的功能相似,下面就在类中添加一个方法来测试一下吧。代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

public void ParallelForMethod()

 {

 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.");

  

 }

写了两个循环,做了一些没有意义的事情,目的主要是为了消耗CPU时间,同理在main方法中调用,运行结果如下图:

可以看到,Parallel.For所用的时间比单纯的for快了1秒多,可见提升的性能是非常可观的。那么,是不是Parallel.For在任何时候都比for要快呢?答案当然是“不是”,要不然微软还留着for干嘛?

下面修改一下代码,添加一个全局变量num,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

public void ParallelForMethod()

 {

 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.");

  

 }

Parallel.For由于是并行运行的,所以会同时访问全局变量num,为了得到正确的结果,要使用lock,此时来看看运行结果:

  是不是大吃一惊啊?Parallel.For竟然用了15秒多,而for跟之前的差不多。这主要是由于并行同时访问全局变量,会出现资源争夺,大多数时间消耗在了资源等待上面。

一直说并行,那么从哪里可以看出来Parallel.For是并行执行的呢?下面来写个测试代码:

1

2

3

4

Parallel.For(0, 100, i =>

 {

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

 });

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

3、Parallel.Foreach

这个方法跟Foreach方法很相似,想具体了解的,可以百度些资料看看,这里就不多说了,下面给出其使用方法:

1

2

3

4

5

6

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

 list.Add(0);

 Parallel.ForEach(list, item =>

 {

 DoWork(item);

 });

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

1、当我们使用到Parallel,必然是处理一些比较耗时的操作,当然也很耗CPU和内存,如果我们中途向停止,怎么办呢?

在串行代码中我们break一下就搞定了,但是并行就不是这么简单了,不过没关系,在并行循环的委托参数中提供了一个ParallelLoopState,

该实例提供了Break和Stop方法来帮我们实现。

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

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

下面来写一段代码测试一下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

public void ParallelBreak()

 {

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

 stopWatch.Start();

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

 {

 if (bag.Count == 300)

 {

  state.Stop();

  return;

 }

 bag.Add(i);

 });

 stopWatch.Stop();

 Console.WriteLine("Bag count is " + bag.Count + ", " + stopWatch.ElapsedMilliseconds);

 }

这里使用的是Stop,当数量达到300个时,会立刻停止;可以看到结果"Bag count is 300",如果用break,可能结果是300多个或者300个,大家可以测试一下。

2、异常处理

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

public class ParallelDemo

 {

 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.");

 }

顺序调用方法我把异常处理写一起了,这样只能捕获Run1的异常信息,大家可以分开写。捕获AggregateException 异常后,用foreach循环遍历输出异常信息,可以看到两个异常信息都显示了。

点击这里,下载源码

以上就是c# 并行和多线程编程——认识Parallel的详细内容,更多关于c# 并行和多线程编程的资料请关注脚本之家其它相关文章!

相关文章:

[C#]Parallel使用

一、 Parallel的使用 1、Parallel.Invoke2、Parallel.For3、Parallel.Foreach二、 Parallel中途退出循环和异常处理 1、当我们使用到Parallel&#xff0c;必然是处理一些比较耗时的操作&#xff0c;当然也很耗CPU和内存&#xff0c;如果我们中途向停止&#xff0c;怎么办呢&…...

docker container 指定gpu设备

1&#xff0c; 在yaml中 Turn on GPU access with Docker Compose | Docker Docs Example of a Compose file for running a service with access to 1 GPU device: services:test:image: nvidia/cuda:12.3.1-base-ubuntu20.04command: nvidia-smideploy:resources:reserva…...

时间Date

你有没有思考过时间问题&#xff1a; 前端为什么可以直接看见时间格式的数据 后端怎么接受的数据&#xff0c;怎么处理的 一般来说&#xff1a;前端传输来数据都是时间格式的字符串&#xff0c;那么后端需要能够解析时间格式的字符串&#xff0c;归功于JSONFormat ,可以解析…...

前端---css 选择器

1. css 选择器的定义 css 选择器是用来选择标签的&#xff0c;选出来以后给标签加样式。 2. css 选择器的种类 标签选择器类选择器层级选择器(后代选择器)id选择器组选择器伪类选择器 3. 标签选择器 根据标签来选择标签&#xff0c;以标签开头&#xff0c;此种选择器影响范…...

【MybatisPlus快速入门】(2)SpringBoot整合MybatisPlus 之 标准数据层开发 代码示例

目录 1 标准CRUD使用2 新增3 删除4 修改5 根据ID查询6 查询所有7 MyBatis-Plus CRUD总结 之前我们已学习MyBatisPlus在代码示例与MyBatisPlus的简介&#xff0c;在这一节中我们重点学习的是数据层标准的CRUD(增删改查)的实现与分页功能。代码比较多&#xff0c;我们一个个来学习…...

如何将自建的ElasticSearch注册成一个服务

ES 服务管理 注册ES服务 创建一个 Elasticsearch 服务配置文件。 ​ sudo vim /etc/systemd/system/elasticsearch.service 将以下内容复制到 elasticsearch.service 文件中&#xff1a; [Unit] Descriptionelasticsearch Afternetwork.target[Service] Typeforking Useresa…...

360勒索病毒:了解最新变种.360,以及如何保护您的数据

导言&#xff1a; 随着科技的飞速发展&#xff0c;网络安全威胁也在不断演变&#xff0c;.360 勒索病毒成为近期备受关注的一种恶意软件。本文91数据恢复将介绍如何恢复被.360 勒索病毒加密的数据文件&#xff0c;并提供一些建议&#xff0c;帮助你预防这种威胁。 如果您在面对…...

vue使用ElementUI搭建精美页面入门

ElementUI简直是css学得不好的同学的福音 ElementUI官网&#xff1a; Element - The worlds most popular Vue UI framework 安装 在vue文件下&#xff0c;用这个命令去安装Element UI。 npm i element-ui -S step1\先切换到vue的目录下去&#xff0c;注意这里面的WARN不是…...

【C->Cpp】深度解析#由C迈向Cpp(2)

目录 &#xff08;一&#xff09;缺省参数 全缺省参数 半缺省参数 缺省参数只能在函数的声明中出现&#xff1a; 小结&#xff1a; &#xff08;二&#xff09;函数重载 函数重载的定义 三种重载 在上一篇中&#xff0c;我们从第一个Cpp程序为切入&#xff0c;讲解了Cpp的…...

WPS中如何根据身份证号生成出生日期并排序

1. wps中如何根据身份证号导出出生日期并排序 1.1 wps中建一张表 1.2 使用转日期格式导出出生日期 DATE(VALUE(MID(C2,7,4)),VALUE(MID(C2,11,2)),VALUE(MID(C2,13,2)))MID(C2, 7, 4)&#xff1a;这部分从单元格 C2 中提取文本字符串&#xff0c;从第7个字符开始提取长度为4的…...

20231222给NanoPC-T4(RK3399)开发板的适配Android11的挖掘机方案并跑通AP6398SV

20231222给NanoPC-T4(RK3399)开发板的适配Android11的挖掘机方案并跑通AP6398SV 2023/12/22 7:54 简略步骤&#xff1a;rootrootrootroot-X99-Turbo:~/3TB$ cat Android11.0.tar.bz2.a* > Android11.0.tar.bz2 rootrootrootroot-X99-Turbo:~/3TB$ tar jxvf Android11.0.tar.…...

iClient for JavaScript如何以mvt矢量瓦片的形式加载数据服务

刘大 这里写目录标题 前言1.iServer中的预览页面2.iClient for JavaScript加载2.1 构建Style2.2 iCient加载2.2.1Leaflet & MapboxGL2.2.2 OpenLayers 前言 在提到查看iServer REST数据服务的概况的时候&#xff0c;大家总会想到说&#xff0c;通过发布对应的地图服务或者…...

全方位掌握卷积神经网络:理解原理 优化实践应用

计算机视觉CV的发展 检测任务 分类与检索 超分辨率重构 医学任务 无人驾驶 整体网络架构 卷积层和激活函数&#xff08;ReLU&#xff09;的组合是网络的核心组成部分 激活函数(ReLU&#xff09; 引入非线性&#xff0c;增强网络的表达能力。 卷积层 负责特征提取 池化层…...

视频批量处理:随机分割方法,创新剪辑方式

随着数字媒体技术的飞速发展&#xff0c;视频处理已是日常生活和工作中不可或缺的一部分。在处理大量视频时&#xff0c;要一种高效、自动化的方法来满足需求。现在一起来看云炫AI智剪如何批量随机分割视频的批量处理方法&#xff0c;给视频剪辑工作带来创新。 视频随机分割4段…...

Gaussian-Splatting 训练并导入Unity中

这个周末玩点啥~&#x1f41e; &#x1f365;环境安装&#x1f4a1;安装C编译工具&#x1f4a1;安装Python&#x1f4a1;安装CUDA&#x1f4a1;添加ffmpeg到环境变量Path添加COLMAP-3.8-windows-cuda文件路径到环境变量Path&#x1f4a1;pytorch安装&#x1f4a1;tqdm 安装&…...

账号和权限管理

目录 一、用户账号和的概述 &#xff08;一&#xff09;用户类别 &#xff08;二&#xff09;组账号 ​编辑&#xff08;三&#xff09;UID号 ​编辑&#xff08;四&#xff09;GID号 &#xff08;五&#xff09;配置文件 二、用户账号管理 &#xff08;一&#xff09;…...

前端---表单标签

1. 表单的介绍 表单用于搜集不同类型的用户输入(用户输入的数据)&#xff0c;然后可以把用户数据提交到web服务器 。 2. 表单相关标签的使用 <form>标签 表示表单标签&#xff0c;定义整体的表单区域 <label>标签 表示表单元素的文字标注标签&#xff0c;定义文字…...

Matplotlib 绘制基本的图表

# 导入包 import pandas as pd import numpy as np import matplotlib.pyplot as plt plt.rcParams[font.sans-serif][SimHei] # 用来显示中文 plt.rcParams[axes.unicode_minus] False # 显示负坐标轴# 读取源数据&#xff0c;后续大部分数据基于词文件的数据&#xff0c;需…...

【JavaScript】异步解决方案的发展历程

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…...

前端性能优化三十四:花裤衩模板引入打包分析工具

测量各个插件和loader所花费的时间 (1). install: yarn add speed-measure-webpack-plugin -D(2). Vue-cli 3.x设置: const SpeedMeasurePlugin require(speed-measure-webpack-plugin) const smp new SpeedMeasurePlugin({outputFormat: human }) // 包裹configureWebpac…...

不止于读写:在HC32F460上为FATFS和SDIO驱动添加调试信息与性能测试

HC32F460深度优化&#xff1a;FATFS与SDIO驱动的调试技巧与性能压测实战 当你的HC32F460开发板已经能够读取SD卡文件时&#xff0c;真正的挑战才刚刚开始。那些隐藏在初始化失败、数据错位、速度瓶颈背后的秘密&#xff0c;往往需要更精密的调试手段才能揭开。本文将带你超越基…...

禅修运维法:服务器宕机时集体冥想

当技术危机遇上心灵平静在软件测试领域&#xff0c;服务器宕机是高频挑战&#xff0c;不仅中断测试流程&#xff0c;还引发团队压力。传统运维强调硬件修复和代码调试&#xff0c;但忽略了人的因素——压力下的决策失误往往加剧问题。禅修运维法创新性地将佛教禅修融入IT管理&a…...

Wan2.2-T2V-A5B提示词怎么写?新手快速出效果的实用指南

Wan2.2-T2V-A5B提示词怎么写&#xff1f;新手快速出效果的实用指南 1. 认识Wan2.2-T2V-A5B视频生成模型 Wan2.2-T2V-A5B是一款由通义万相开源的轻量级文本到视频生成模型&#xff0c;拥有50亿参数规模。虽然它生成的视频分辨率是480P&#xff0c;但在时序连贯性和运动推理能力…...

3步实现跨次元游戏模组管理:XXMI启动器的多游戏统一解决方案

3步实现跨次元游戏模组管理&#xff1a;XXMI启动器的多游戏统一解决方案 【免费下载链接】XXMI-Launcher Modding platform for GI, HSR, WW and ZZZ 项目地址: https://gitcode.com/gh_mirrors/xx/XXMI-Launcher 还在为《原神》《崩坏&#xff1a;星穹铁道》等多款二次…...

Llama-3.2V-11B-cot镜像免配置:内置模型加载进度条与超时重试机制

Llama-3.2V-11B-cot镜像免配置&#xff1a;内置模型加载进度条与超时重试机制 1. 项目概述 Llama-3.2V-11B-cot是基于Meta Llama-3.2V-11B-cot多模态大模型开发的高性能视觉推理工具&#xff0c;专为双卡4090环境深度优化。这个工具解决了传统大模型部署中的多个痛点&#xf…...

打破3D创作壁垒:零成本解决方案实现Blender到Unreal Engine的无缝资产迁移

打破3D创作壁垒&#xff1a;零成本解决方案实现Blender到Unreal Engine的无缝资产迁移 【免费下载链接】bl_datasmith Blender addon to export UE4 Datasmith format 项目地址: https://gitcode.com/gh_mirrors/bl/bl_datasmith 你是否也曾因格式转换丢失过数小时的工作…...

OpenClaw环境迁移:GLM-4.7-Flash配置的备份与恢复方案

OpenClaw环境迁移&#xff1a;GLM-4.7-Flash配置的备份与恢复方案 1. 为什么需要环境迁移&#xff1f; 上周我的主力开发机突然硬盘故障&#xff0c;导致所有OpenClaw配置丢失。最痛心的是花了两周调试的GLM-4.7-Flash对接设置全部归零——包括精心调整的温度参数、自定义提示…...

GNSS说第(八)讲---自适应动态导航定位(八)---抗差估计在复杂环境下的应用实践

1. 抗差估计&#xff1a;GNSS定位的"防弹衣" 想象一下你在高楼林立的城市峡谷中打开手机导航&#xff0c;信号时断时续&#xff0c;定位图标像喝醉酒一样到处乱飘——这就是典型的多路径干扰场景。传统最小二乘法就像用普通尺子测量扭曲的橡皮筋&#xff0c;单个异常…...

避坑指南:用ESP32驱动LD2420毫米波雷达时,串口数据丢失和自动开机卡死的那些事儿

ESP32与LD2420毫米波雷达深度避坑实战&#xff1a;从数据丢失到系统卡死的全链路解决方案 当你在凌晨三点盯着逻辑分析仪上那些残缺的串口波形时&#xff0c;就会明白为什么LD2420毫米波雷达被称为"最熟悉的陌生人"。这个能穿透墙壁感知呼吸的24GHz传感器&#xff0c…...

Win11Debloat:Windows系统轻量优化解决方案

Win11Debloat&#xff1a;Windows系统轻量优化解决方案 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本&#xff0c;用于从Windows中移除预装的无用软件&#xff0c;禁用遥测&#xff0c;从Windows搜索中移除Bing&#xff0c;以及执行各种其他更改以简化和改善你的Win…...