[C#]Parallel使用
- 一、 Parallel的使用
- 1、Parallel.Invoke
- 2、Parallel.For
- 3、Parallel.Foreach
- 二、 Parallel中途退出循环和异常处理
- 1、当我们使用到Parallel,必然是处理一些比较耗时的操作,当然也很耗CPU和内存,如果我们中途向停止,怎么办呢?
- 2、异常处理
随着多核时代的到来,并行开发越来越展示出它的强大威力!使用并行程序,充分的利用系统资源,提高程序的性能。在.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,必然是处理一些比较耗时的操作,当然也很耗CPU和内存,如果我们中途向停止,怎么办呢&…...
docker container 指定gpu设备
1, 在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
你有没有思考过时间问题: 前端为什么可以直接看见时间格式的数据 后端怎么接受的数据,怎么处理的 一般来说:前端传输来数据都是时间格式的字符串,那么后端需要能够解析时间格式的字符串,归功于JSONFormat ,可以解析…...
前端---css 选择器
1. css 选择器的定义 css 选择器是用来选择标签的,选出来以后给标签加样式。 2. css 选择器的种类 标签选择器类选择器层级选择器(后代选择器)id选择器组选择器伪类选择器 3. 标签选择器 根据标签来选择标签,以标签开头,此种选择器影响范…...

【MybatisPlus快速入门】(2)SpringBoot整合MybatisPlus 之 标准数据层开发 代码示例
目录 1 标准CRUD使用2 新增3 删除4 修改5 根据ID查询6 查询所有7 MyBatis-Plus CRUD总结 之前我们已学习MyBatisPlus在代码示例与MyBatisPlus的简介,在这一节中我们重点学习的是数据层标准的CRUD(增删改查)的实现与分页功能。代码比较多,我们一个个来学习…...
如何将自建的ElasticSearch注册成一个服务
ES 服务管理 注册ES服务 创建一个 Elasticsearch 服务配置文件。 sudo vim /etc/systemd/system/elasticsearch.service 将以下内容复制到 elasticsearch.service 文件中: [Unit] Descriptionelasticsearch Afternetwork.target[Service] Typeforking Useresa…...
360勒索病毒:了解最新变种.360,以及如何保护您的数据
导言: 随着科技的飞速发展,网络安全威胁也在不断演变,.360 勒索病毒成为近期备受关注的一种恶意软件。本文91数据恢复将介绍如何恢复被.360 勒索病毒加密的数据文件,并提供一些建议,帮助你预防这种威胁。 如果您在面对…...

vue使用ElementUI搭建精美页面入门
ElementUI简直是css学得不好的同学的福音 ElementUI官网: Element - The worlds most popular Vue UI framework 安装 在vue文件下,用这个命令去安装Element UI。 npm i element-ui -S step1\先切换到vue的目录下去,注意这里面的WARN不是…...

【C->Cpp】深度解析#由C迈向Cpp(2)
目录 (一)缺省参数 全缺省参数 半缺省参数 缺省参数只能在函数的声明中出现: 小结: (二)函数重载 函数重载的定义 三种重载 在上一篇中,我们从第一个Cpp程序为切入,讲解了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):这部分从单元格 C2 中提取文本字符串,从第7个字符开始提取长度为4的…...

20231222给NanoPC-T4(RK3399)开发板的适配Android11的挖掘机方案并跑通AP6398SV
20231222给NanoPC-T4(RK3399)开发板的适配Android11的挖掘机方案并跑通AP6398SV 2023/12/22 7:54 简略步骤: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数据服务的概况的时候,大家总会想到说,通过发布对应的地图服务或者…...

全方位掌握卷积神经网络:理解原理 优化实践应用
计算机视觉CV的发展 检测任务 分类与检索 超分辨率重构 医学任务 无人驾驶 整体网络架构 卷积层和激活函数(ReLU)的组合是网络的核心组成部分 激活函数(ReLU) 引入非线性,增强网络的表达能力。 卷积层 负责特征提取 池化层…...

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

Gaussian-Splatting 训练并导入Unity中
这个周末玩点啥~🐞 🍥环境安装💡安装C编译工具💡安装Python💡安装CUDA💡添加ffmpeg到环境变量Path添加COLMAP-3.8-windows-cuda文件路径到环境变量Path💡pytorch安装💡tqdm 安装&…...

账号和权限管理
目录 一、用户账号和的概述 (一)用户类别 (二)组账号 编辑(三)UID号 编辑(四)GID号 (五)配置文件 二、用户账号管理 (一)…...
前端---表单标签
1. 表单的介绍 表单用于搜集不同类型的用户输入(用户输入的数据),然后可以把用户数据提交到web服务器 。 2. 表单相关标签的使用 <form>标签 表示表单标签,定义整体的表单区域 <label>标签 表示表单元素的文字标注标签,定义文字…...

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 # 显示负坐标轴# 读取源数据,后续大部分数据基于词文件的数据,需…...

【JavaScript】异步解决方案的发展历程
✨ 专栏介绍 在现代Web开发中,JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性,还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言,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…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...