前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >NetCore并发编程

NetCore并发编程

原创
作者头像
逸鹏
发布于 2018-09-07 00:34:49
发布于 2018-09-07 00:34:49
2.7K00
代码可运行
举报
文章被收录于专栏:逸鹏说道逸鹏说道
运行总次数:0
代码可运行

NetCore并发编程

示例代码:https://github.com/lotapp/BaseCode/tree/master/netcore/4_Concurrency

先简单说下概念(其实之前也有说,所以简说下):

  1. 并发:同时做多件事情
  2. 多线程:并发的一种形式
  3. 并行处理:多线程的一种(线程池产生的一种并发类型,eg:异步编程
  4. 响应式编程:一种编程模式,对事件进行响应(有点类似于JQ的事件)

Net里面很少用进程,在以前基本上都是 线程+池+异步+并行+协程

我这边简单引入一下,毕竟主要是写Python的教程,Net只是帮你们回顾一下,如果你发现还没听过这些概念,或者你的项目中还充斥着各种 ThreadThreadPool的话,真的得系统的学习一下了,现在官网的文档已经很完善了,记得早几年啥都没有,也只能挖那些外国开源项目:

https://docs.microsoft.com/zh-cn/dotnet/standard/parallel-processing-and-concurrency

1.异步编程(Task)

Task的目的其实就是为了简化 ThreadThreadPool的代码,下面一起看看吧:

异步用起来比较简单,一般IO,DB,Net用的比较多,很多时候都会采用重试机制,举个简单的例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// <summary>/// 模拟一个网络操作(别忘了重试机制)/// </summary>/// <param name="url">url</param>/// <returns></returns>private async static Task<string> DownloadStringAsync(string url){    using (var client = new HttpClient())    {        // 设置第一次重试时间        var nextDelay = TimeSpan.FromSeconds(1);        for (int i = 0; i < 3; i++)        {            try            {                return await client.GetStringAsync(url);            }            catch { }            await Task.Delay(nextDelay); // 用异步阻塞的方式防止服务器被太多重试给阻塞了            nextDelay *= 2; // 3次重试机会,第一次1s,第二次2s,第三次4s        }        // 最后一次尝试,错误就抛出        return await client.GetStringAsync(url);    }}

然后补充说下Task异常的问题,当你await的时候如果有异常会抛出,在第一个await处捕获处理即可

如果 asyncawait就是理解不了的可以这样想: async就是为了让 await生效(为了向后兼容)

对了,如果返回的是void,你设置成Task就行了,触发是类似于事件之类的方法才使用void,不然没有返回值都是使用Task

项目里经常有这么一个场景:等待一组任务完成后再执行某个操作,看个引入案例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// <summary>/// 1.批量任务/// </summary>/// <param name="list"></param>/// <returns></returns>private async static Task<string[]> DownloadStringAsync(IEnumerable<string> list){    using (var client = new HttpClient())    {        var tasks = list.Select(url => client.GetStringAsync(url)).ToArray();        return await Task.WhenAll(tasks);    }}

再举一个场景:同时调用多个同效果的API,有一个返回就好了,其他的忽略

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// <summary>/// 2.返回首先完成的Task/// </summary>/// <param name="list"></param>/// <returns></returns>private static async Task<string> GetIPAsync(IEnumerable<string> list){    using (var client = new HttpClient())    {        var tasks = list.Select(url => client.GetStringAsync(url)).ToArray();        var task = await Task.WhenAny(tasks); // 返回第一个完成的Task        return await task;    }}

一个async方法被await调用后,当它恢复运行时就会回到原来的上下文中运行。

如果你的Task不再需要上下文了可以使用: task.ConfigureAwait(false),eg:写个日记还要啥上下文?

逆天的建议是:在核心代码里面一种使用 ConfigureAwait,用户页面相关代码,不需要上下文的加上

其实如果有太多await在上下文里恢复那也是比较卡的,使用 ConfigureAwait之后,被暂停后会在线程池里面继续运行

再看一个场景:比如一个耗时操作,我需要指定它的超时时间:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 /// <summary>/// 3.超时取消/// </summary>/// <returns></returns>private static async Task<string> CancellMethod(){    //实例化取消任务    var cts = new CancellationTokenSource();    cts.CancelAfter(TimeSpan.FromSeconds(3)); // 设置失效时间为3s    try    {        return await DoSomethingAsync(cts.Token);    }    // 任务已经取消会引发TaskCanceledException    catch (TaskCanceledException ex)    {        return "false";    }}/// <summary>/// 模仿一个耗时操作/// </summary>/// <returns></returns>private static async Task<string> DoSomethingAsync(CancellationToken token){    await Task.Delay(TimeSpan.FromSeconds(5), token);    return "ok";}

异步这块简单回顾就不说了,留两个扩展,你们自行探讨:

  1. 进度方面的可以使用 IProgress<T>,就当留个作业自己摸索下吧~
  2. 使用了异步之后尽量避免使用 task.Wait or task.Result,这样可以避免死锁

Task其他新特征去官网看看吧,引入到此为止了。


2.并行编程(Parallel)

这个其实出来很久了,现在基本上都是用 PLinq比较多点,主要就是:

  1. 数据并行:重点在处理数据(eg:聚合)
  2. 任务并行:重点在执行任务(每个任务块尽可能独立,越独立效率越高)
数据并行

以前都是 Parallel.ForEach这么用,现在和Linq结合之后非常方便 .AsParallel()就OK了

说很抽象看个简单案例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static void Main(string[] args){    IEnumerable<int> list = new List<int>() { 1, 2, 3, 4, 5, 7, 8, 9 };    foreach (var item in ParallelMethod(list))    {        Console.WriteLine(item);    }}/// <summary>/// 举个例子/// </summary>private static IEnumerable<int> ParallelMethod(IEnumerable<int> list){    return list.AsParallel().Select(x => x * x);}

正常执行的结果应该是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1492564164981

并行之后就是这样了(不管顺序了):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2564194981416

当然了,如果你就是对顺序有要求可以使用: .AsOrdered()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// <summary>/// 举个例子/// </summary>private static IEnumerable<int> ParallelMethod(IEnumerable<int> list){    return list.AsParallel().AsOrdered().Select(x => x * x);}

其实实际项目中,使用并行的时候:任务时间适中,太长不适合,太短也不适合

记得大家在项目里经常会用到如 SumCount等聚合函数,其实这时候使用并行就很合适

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var list = new List<long>();for (long i = 0; i < 1000000; i++){    list.Add(i);}Console.WriteLine(GetSumParallel(list));
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static long GetSumParallel(IEnumerable<long> list){    return list.AsParallel().Sum();}

time dotnet PLINQ.dll

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
499999500000real    0m0.096suser    0m0.081ssys    0m0.025s

不使用并行:(稍微多了点,CPU越密集差距越大)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
499999500000real    0m0.103suser    0m0.092ssys    0m0.021s

其实聚合有一个通用方法,可以支持复杂的聚合:(以上面sum为例)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.Aggregate(            seed:0,            func:(sum,item)=>sum+item          );

稍微扩展一下,PLinq也是支持取消的, .WithCancellation(CancellationToken)

Token的用法和上面一样,就不复述了,如果需要和异步结合,一个 Task.Run就可以把并行任务交给线程池了

也可以使用Task的异步方法,设置超时时间,这样PLinq超时了也就终止了

PLinq这么方便,其实也是有一些小弊端的,比如它会直接最大程度的占用系统资源,可能会影响其他的任务,而传统的Parallel则会动态调整


任务并行(并行调用)

这个PLinq好像没有对应的方法,有新语法你可以说下,来举个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
await Task.Run(() =>    Parallel.Invoke(        () => Task.Delay(TimeSpan.FromSeconds(3)),        () => Task.Delay(TimeSpan.FromSeconds(2))    ));

取消也支持:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Parallel.Invoke(new ParallelOptions() { CancellationToken = token }, actions);

扩充说明

其实还有一些比如数据流响应编程没说,这个之前都是用第三方库,刚才看官网文档,好像已经支持了,所以就不卖弄了,感兴趣的可以去看看,其实项目里面有流数据相关的框架,eg: Spark,都是比较成熟的解决方案了基本上也不太使用这些了。

然后还有一些没说,比如NetCore里面不可变类型(列表、字典、集合、队列、栈、线程安全字典等等)以及限流任务调度等,这些关键词我提一下,也方便你去搜索自己学习拓展

先到这吧,其他的自己探索一下吧,最后贴一些Nuget库,你可以针对性的使用:

  1. 数据流Microsoft.Tpl.Dataflow
  2. 响应编程(Linq的Rx操作): Rx-Main
  3. 不可变类型Microsoft.Bcl.Immutable

不得不感慨一句,微软妈妈真的花了很多功夫,Net的并发编程比Python省心多了(完)

https://www.cnblogs.com/dotnetcrazy/p/9426279.html

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
基于YOLOv8的河道垃圾塑料瓶子识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
源码包含:完整YOLOv8训练代码+数据集(带标注)+权重文件+直接可允许检测的yolo检测程序+直接部署教程/训练教程
一键难忘
2025/06/08
1160
基于YOLOv8的PCB缺陷检测识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
源码包含:完整YOLOv8训练代码+数据集(带标注)+权重文件+直接可允许检测的yolo检测程序+直接部署教程/训练教程
一键难忘
2025/06/07
1150
基于YOLOv8的火灾识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
源码包含:完整YOLOv8训练代码+2k张数据集(带标注)+权重文件+直接可允许检测的yolo检测程序+直接部署教程/训练教程。源码打包在文末。
一键难忘
2025/06/06
1350
基于YOLOv8的7种交通场景识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
哔哩哔哩:https://www.bilibili.com/video/BV1yajdzdEvu/
一键难忘
2025/05/27
4820
基于YOLOv8的路面缝隙精准识别项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】
哔哩哔哩:https://www.bilibili.com/video/BV1EojzziEKx/
一键难忘
2025/05/28
1870
基于YOLOv8的6种金属表面缺陷检测识别项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】
源码包含:完整YOLOv8训练代码+2万张数据集(带标注)+权重文件+直接可允许检测的yolo检测程序+直接部署教程/训练教程。源码见文末
一键难忘
2025/05/30
2410
基于YOLOv8的交通标识及设施识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
本项目集成了 YOLOv8 交通标识检测模型 与 PyQt5 图形交互界面,实现了对交通场景中关键目标的自动识别功能,涵盖:人行横道、限速标志、停车标志与交通信号灯。
一键难忘
2025/06/10
1380
基于YOLOv8的人脸表情识别项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用】
本项目集成了 YOLOv8 表情检测模型 与 PyQt5 图形界面工具,实现了包括图片、文件夹、视频与摄像头等多种输入方式的人脸表情识别功能。配套完整源码与训练流程说明,让你开箱即用、快速部署自己的情绪识别系统,源码打包在文末。
一键难忘
2025/05/26
5120
基于YOLOv8的路面缺陷(路面裂缝、井盖、坑洼路面)识别项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】
哔哩哔哩:https://www.bilibili.com/video/BV1iy75zhEgM/
一键难忘
2025/05/29
1410
基于YOLOv8的汽车车牌位置实时检测项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】
源码包含:完整YOLOv8训练代码+2万张数据集(带标注)+权重文件+直接可允许检测的yolo检测程序+直接部署教程/训练教程
一键难忘
2025/05/31
4320
基于YOLOv8的坐姿标准姿态检测项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】
源码包含:完整YOLOv8训练代码+数据集(带标注)+权重文件+直接可允许检测的yolo检测程序+直接部署教程/训练教程
一键难忘
2025/06/03
1530
基于YOLOv8的摔倒行为检测系统(Python源码+Pyqt6界面+数据集)
💡💡💡本文主要内容:通过实战基于YOLOv8的摔倒行为检测算法,从数据集制作到模型训练,最后设计成为检测UI界面
AI小怪兽
2024/01/23
2.3K0
YOLOv8已至,精度大涨!教你如何在自定义数据集上训练它
丰色 发自 凹非寺 量子位 | 公众号 QbitAI 很快啊—— 目标检测经典模型YOLO的第八个版本就已经发布了。 这次升级不少,包括命令行界面、Python API、backbone结构等,精度相比YOLOv5高了一大截(速度官方还没公布)。 下面是网友实测,几个不同规模的变体在目标检测、实例分割和图像分类三项任务上的涨点最高达到了33.21%。 不知道YOLOv8这一出,v5版本还会“苟”多久? oh我们还发现已经有人用它在自定义数据集上完成了一波训练,效果是这样滴: 这精准度和稳定性,让网友狠
量子位
2023/02/28
4.1K0
YOLOv8已至,精度大涨!教你如何在自定义数据集上训练它
从零开始学习 YOLOv8:目标检测与车牌识别实例
目标检测就像是在寻找隐藏的宝藏。想象一下,你在一个巨大的图画里,里面藏着无数的物体,而你的任务是迅速找到其中的几样,比如说,一只流浪的小猫和一辆红色的小轿车。目标检测就是让计算机“眼明手快”,准确找出这些目标,甚至告诉你“喵,那个小猫正躲在花丛里!”
繁依Fanyi
2024/10/23
1.4K0
从零开始学习 YOLOv8:目标检测与车牌识别实例
基于YOLOv8的摄像头吸烟行为检测系统(Python源码+Pyqt6界面+数据集)
💡💡💡本文主要内容:详细介绍了摄像头下吸烟行为检测系统,在介绍算法原理的同时,给出Pytorch的源码、训练数据集以及PyQt6的UI界面。在界面中可以选择各种图片、视频进行检测识别,可进行置信度、Iou阈值设定,结果可视化等。
AI小怪兽
2024/01/29
1.8K5
基于YOLOv8的船舶目标检测系统(Python源码+Pyqt6界面+数据集)
💡💡💡本文主要内容:详细介绍了船舶目标检测系统,在介绍算法原理的同时,给出Pytorch的源码、训练数据集以及PyQt6的UI界面。在界面中可以选择各种图片、视频进行检测识别,可进行置信度、Iou阈值设定,结果可视化等。
AI小怪兽
2024/01/30
1.8K0
基于YOLOv8的足球赛环境下足球目标检测系统(Python源码+Pyqt6界面+数据集)
💡💡💡本文主要内容:详细介绍了足球赛环境下足球目标检测系统,在介绍算法原理的同时,给出Pytorch的源码、训练数据集以及PyQt6的UI界面。在界面中可以选择各种图片、视频进行检测识别,可进行置信度、Iou阈值设定,结果可视化等。
AI小怪兽
2024/02/07
8240
YOLOv8 深度解析!一文看懂,快速上手实操(附实践代码)
开源地址:https://github.com/ultralytics/ultralytics
计算机视觉研究院
2023/08/24
30.7K0
YOLOv8 深度解析!一文看懂,快速上手实操(附实践代码)
​基于 YOLOv8 和计算机视觉 CV 的实时识别系统!
在当今技术创新的背景下,各领域的进步已经改变了人类的存在方式,从教育(Abulibdeh等人,2024年)和医疗保健(Younis等人,2024年)到娱乐(Takale等人,2024年)和通信(Gholami和Al Abdwani,2024年)。尽管这些变革性的进步已经发生,但某些社区仍然面临阻碍他们获得基本特权的障碍。
AIGC 先锋科技
2024/07/08
6900
​基于 YOLOv8 和计算机视觉 CV 的实时识别系统!
实战 | 本地GPU训练YOLOv8带方向的目标检测
目标检测是指在图像或视频帧内识别和定位物体的任务。定向目标检测具体涉及检测具有定义方向或旋转的物体,例如检测具有不同角度的车辆或检测自然场景中具有不同方向的文本。
Color Space
2024/06/21
1.6K0
实战 | 本地GPU训练YOLOv8带方向的目标检测
推荐阅读
基于YOLOv8的河道垃圾塑料瓶子识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
1160
基于YOLOv8的PCB缺陷检测识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
1150
基于YOLOv8的火灾识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
1350
基于YOLOv8的7种交通场景识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
4820
基于YOLOv8的路面缝隙精准识别项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】
1870
基于YOLOv8的6种金属表面缺陷检测识别项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】
2410
基于YOLOv8的交通标识及设施识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
1380
基于YOLOv8的人脸表情识别项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用】
5120
基于YOLOv8的路面缺陷(路面裂缝、井盖、坑洼路面)识别项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】
1410
基于YOLOv8的汽车车牌位置实时检测项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】
4320
基于YOLOv8的坐姿标准姿态检测项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】
1530
基于YOLOv8的摔倒行为检测系统(Python源码+Pyqt6界面+数据集)
2.3K0
YOLOv8已至,精度大涨!教你如何在自定义数据集上训练它
4.1K0
从零开始学习 YOLOv8:目标检测与车牌识别实例
1.4K0
基于YOLOv8的摄像头吸烟行为检测系统(Python源码+Pyqt6界面+数据集)
1.8K5
基于YOLOv8的船舶目标检测系统(Python源码+Pyqt6界面+数据集)
1.8K0
基于YOLOv8的足球赛环境下足球目标检测系统(Python源码+Pyqt6界面+数据集)
8240
YOLOv8 深度解析!一文看懂,快速上手实操(附实践代码)
30.7K0
​基于 YOLOv8 和计算机视觉 CV 的实时识别系统!
6900
实战 | 本地GPU训练YOLOv8带方向的目标检测
1.6K0
相关推荐
基于YOLOv8的河道垃圾塑料瓶子识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档