首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
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 删除。

评论
登录后参与评论
暂无评论
推荐阅读
视频逐帧读取并保存至指定文件夹(opencv之python描述)
frame = video.read()
用户4908836
2020/04/14
1.9K0
tf27: Deep Dream—应用到视频
本文介绍了如何将Deep Dream技术应用于视频上,通过使用TensorFlow和Python实现Deep Dream算法,从而对视频进行逐帧处理,产生具有梦幻效果的视频。同时,也介绍了一些相关的工具和库,如ffmpeg、numpy、scipy、scikit-learn等,这些工具可以帮助我们更好地实现Deep Dream算法。此外,还介绍了一些Deep Dream算法的应用,如图像风格转换、图像修复、图像超分辨率等。最后,也介绍了一些实现Deep Dream算法的技巧和最佳实践,如调整网络结构、选择合适的预训练模型、使用预训练权重等。通过本文的学习,我们可以更好地理解Deep Dream算法,并能够将其应用于实际的视频处理任务中。"
MachineLP
2018/01/09
6750
打破次元壁,让游戏角色在指尖跳舞,简易的 AR 教程
作为一个天涯明月刀游戏的端游老玩家,天刀的画质是没的说的。玩天刀的七年,我唯一最大的收获就是拐了女朋友回家。至此,双十一来临之际,我紧急把之前想写的教程赶了出来。为了让单身的少侠可以在现实世界有自己游戏角色的陪伴,不再那么孤单,我可真是操碎了心,半夜把网页赶了出来。其实单身和非单身的双十一区别不是很大,只是吃土的方式不一样罢了。话不多说,我们先来看下效果:
桑榆肖物
2022/11/18
9980
打破次元壁,让游戏角色在指尖跳舞,简易的 AR 教程
视频2图片video_to_images
发布者:全栈程序员栈长,转转请注明出处:https://javaforall.cn/2158.html原文链接:
全栈程序员站长
2021/04/07
4340
python将视频抽帧的的多种方式
最近有一个需求是将视频抽取为一个个的帧图片,使用python很方便实现,而且有多种方式;
JQ实验室
2022/09/29
3.3K0
Python实现5毛钱特效
Python牛已经不是一天两天的事了,但是我开始也没想到,Python能这么牛。前段时间接触了一个批量抠图的模型库,而后在一些视频中找到灵感,觉得应该可以通过抠图的方式,给视频换一个不同的场景,于是就有了今天的文章。
ZackSock
2020/04/16
1.1K0
Python实现高级电影特效
前几天写了个实现特效的博客,感觉有点差强人意,只是简简单单的换背景应用场景不是非常多,今天就来实现一个更加复杂的特效“影分身”。下面有请我们本场的主演,坤制作人为我们表演他拿手的鸡你太美。
ZackSock
2020/05/18
1.5K0
Python实现高级电影特效
使用 Dify 和 AI 大模型理解视频内容:Qwen 2 VL 72B
本篇作为第一篇内容,以昨天出圈的“黑神话悟空制作人采访视频”为例,先来聊聊经常被国外厂商拿来对比的国产模型:千问系列,以及它的内测版。
soulteary
2024/08/27
1.6K0
使用 Dify 和 AI 大模型理解视频内容:Qwen 2 VL 72B
图片与视频互转(python)
usage example: python video2jpg.py --video 1574393815.avi --out_dir 1574393815
用户4363240
2019/12/08
2K0
使用Python-去除视频背景
no怕不了木
2023/08/08
8040
使用Python-去除视频背景
利用 FFmpeg 批量添加视频水印2025
在当今的数字时代,视频已成为信息传播和品牌推广的重要载体。然而,随着视频内容的广泛传播,如何保护版权、提升品牌辨识度成为许多创作者和企业面临的难题。手动为视频添加水印费时费力,而批量处理则能大幅提升效率。本文将带你了解如何利用 FFmpeg 这一强大工具,结合 Python 编程,实现视频的批量水印添加,让你的视频处理更加高效、智能!
叶子Tenney
2025/03/09
3230
利用 FFmpeg 批量添加视频水印2025
我用 Python 做了个小仙女代码蹦迪视频
https://blog.csdn.net/hhladminhhl/article/details/118463344 (AirPython整理)
昱良
2021/07/27
7910
python带你剪辑视频
嗯,好久没写文章了。因为最近没有熬夜了,天天背电脑也很辛苦。 工作嘛,手工为主,没有啥技术成长,也没啥好写的。 疫情期间,总听到有人叹气,总听到抖音里面“我太难了”。
赵云龙龙
2020/08/13
3.1K0
飞桨PaddleHub带你环游世界,快来试试Python一键视频抠图吧
在视频创作过程中,有时会遇到人像抠图的需求,最一般的做法是使用PR、AE等工具将视频中的每一帧图像手动抠图。这么繁琐的步骤在理工男面前简直是不可存在的,那么有什么简单的方法能快速抠图吗?当然有啦,接下来给大家介绍如何使用PaddleHub一键视频人像抠图。
用户1386409
2020/04/22
1.8K0
使用Python进行网站数据爬取和视频处理
在互联网时代,我们经常需要从网站上获取数据并进行分析或处理。有时候,我们还需要对视频数据进行一些操作,比如剪辑、转码、合成等。Python是一门非常适合做数据分析和视频处理的编程语言,它有很多强大的库和工具可以帮助我们完成这些任务。本文将介绍如何使用Python的requests模块爬取网站数据并进行视频处理的方法和步骤。
jackcode
2023/08/10
6340
使用Python进行网站数据爬取和视频处理
[1214]基于Python实现视频去重
一款基于Python语言的视频去重复程序,它可以根据视频的特征参数,将重复的视频剔除,以减少视频的存储空间。它的基本原理是:首先利用Python语言对视频文件进行解析,提取视频的特征参数,如帧率、码率等;然后根据特征参数,生成视频的哈希值;最后,将每个视频的哈希值进行对比,如果哈希值相同,则表示视频内容相同,可以将其中一个视频剔除,以节省存储空间。
周小董
2023/10/10
6890
python 用opencv接口把视频逐帧转化为图片
好了,接下来我要做一个实际的深度学习图像分割的小项目,项目内容是从一堆拍摄海面的图片中将白浪花分割出来,这个项目的分割只对白浪花感兴趣,所以最后应该是01分割,非黑即白。目前收到800G左右的数据,视频格式,每段大约50分钟。首先要做的就是从这些视频中把每一帧的图片导出来,变成图片。
狼啸风云
2020/07/27
3.3K2
模型实操 | 从零开始,用英伟达T4、A10训练小型文生视频模型
OpenAI 的 Sora、Stability AI 的 Stable Video Diffusion 以及许多其他已经发布或未来将出现的文本生成视频模型,是继大语言模型 (LLM) 之后 2024 年最流行的 AI 趋势之一。
ShuYini
2024/07/04
2760
模型实操 | 从零开始,用英伟达T4、A10训练小型文生视频模型
FFmpeg 在爬虫中的应用案例:流数据解码详解
在大数据时代,网络爬虫技术成为了数据采集的重要手段。FFmpeg 是一个强大的多媒体处理工具,广泛应用于音视频处理领域。在本篇文章中,我们将详细讲解如何将 FFmpeg 应用于网络爬虫技术中,以解码和采集小红书短视频为案例。同时,文章将提供具体的代码示例,包括如何使用代理IP、设置User-Agent和Cookie等技术,提升爬虫的采集成功率。
jackcode
2024/07/23
2240
FFmpeg 在爬虫中的应用案例:流数据解码详解
(强烈推荐)移动端音视频从零到上手(下)
封装就是把编码器生成的音频,视频同步以生成我们肉眼可见,耳朵可听并且看到的与听到的是同步的视频文件.即封装后生成一个容器,来存放音频和视频流以及一些其他信息(比如字幕, metadata等).
音视频开发进阶
2019/07/31
1.2K0
(强烈推荐)移动端音视频从零到上手(下)
相关推荐
视频逐帧读取并保存至指定文件夹(opencv之python描述)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档