当前位置: 首页 > 编程日记 > 正文

Python3 与 C# 并发编程之~ Net篇

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用的比较多,很多时候都会采用重试机制,举个简单的例子:

/// <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

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

/// <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,有一个返回就好了,其他的忽略

/// <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); // 返回第一个完成的Taskreturn await task;}
}

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

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

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

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

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

 /// <summary>
/// 3.超时取消
/// </summary>
/// <returns></returns>
private static async Task<string> CancellMethod()
{//实例化取消任务var cts = new CancellationTokenSource();cts.CancelAfter(TimeSpan.FromSeconds(3)); // 设置失效时间为3stry{return await DoSomethingAsync(cts.Token);}// 任务已经取消会引发TaskCanceledExceptioncatch (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了

说很抽象看个简单案例:

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);
}

正常执行的结果应该是:

1
4
9
25
64
16
49
81

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

25
64
1
9
49
81
4
16

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

/// <summary>
/// 举个例子
/// </summary>
private static IEnumerable<int> ParallelMethod(IEnumerable<int> list)
{return list.AsParallel().AsOrdered().Select(x => x * x);
}

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

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

var list = new List<long>();
for (long i = 0; i < 1000000; i++)
{list.Add(i);
}
Console.WriteLine(GetSumParallel(list));
private static long GetSumParallel(IEnumerable<long> list)
{return list.AsParallel().Sum();
}

time dotnet PLINQ.dll

499999500000real    0m0.096s
user    0m0.081s
sys 0m0.025s

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

499999500000real    0m0.103s
user    0m0.092s
sys 0m0.021s

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

.Aggregate(seed:0,func:(sum,item)=>sum+item);

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

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

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

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


任务并行(并行调用)

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

await Task.Run(() =>Parallel.Invoke(() => Task.Delay(TimeSpan.FromSeconds(3)),() => Task.Delay(TimeSpan.FromSeconds(2))));

取消也支持:

Parallel.Invoke(new ParallelOptions() { CancellationToken = token }, actions);

扩充说明

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

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

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

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

相关文章:

tomcat5.5.9+sql2000数据库连接池配置

终于解决了困扰多天的连接池的问题&#xff0c;写下这编文章与大家一起分享。我是在tomcat5.5.9下配置的&#xff0c;tomcat5.5.X和以前的版本有一些差别&#xff0c;所以配置上也有差别。我就说一下在tomcat5.5.9配置的基本步骤&#xff1a;&#xff08;确定你以安装好tomcat5…

(C++)第一个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字符不变。要求根据密码译回原文,并输出。

题目描述 有一行电文&#xff0c;已按如下规律译成密码&#xff1a; A–>Z a–>z B–>Y b–>y C–>X c–>x … … 即第一个字母变成第26个字母&#xff0c;第i个字母变成第&#xff08;26-i1)个字母&#xff0c;非字母字符不变。要求根据密码译回原文&a…

mysql++读写BLOB数据

mysql读写BLOB数据 1、使用sql_create_n宏函数&#xff0c;建立数据库表字段与对象。 #define sql_create_2(NAME, CMP, CONTR, T1, I1, T2, I2) \ sql_create_complete_2(NAME, CMP, CONTR, T1, I1, #I1, T2, I2, #I2) \ //NAME&#xff1a;表名&#xff1…

oracle RAC的VIP和scan

我们都知道Oracle RAC中每个节点都有一个虚拟IP&#xff0c;简称VIP&#xff0c;与公网IP在同一个网段。 没有VIP时&#xff0c;Oracle客户端是靠“TCP/IP协议栈超时”来判断服务器故障。而TCP/IP协议栈是作为OS Kernel的一部分来实现&#xff0c;不同的OS有不同的阀值&#xf…

2007年你必须学习的10项.NET技术

1、WCF (Windows Communication Foundation):虽然WCF显然没有WPF或SilverLight那么吸引人,但是它却是在.NET框架下解决业务问题的基础。所以你今年至少要学习一门.NET的新技术,那你就选择WCF吧。 2、ADO.NET (and LINQ):这是让你与数据层打交道的技术。并且LINQ提供了将各种数据…

(C++)用指针实现两数交换函数swap()的两种方法

#include<cstdio>//用指针写swap()函数 void swap_1(int* p1,int* p2){int temp *p1;*p1 *p2;*p2 temp; } //用指针和指针的引用写swap()函数 void swap_2(int* &p1,int* &p2){int* temp p1;p1 p2;p2 temp; } int main(){int a 2020,b2021;int *p1&a,…

【转】《iOS7 by Tutorials》系列:iOS7的设计精髓(上)

简介&#xff1a; 本文翻译自《iOS7 by Tutorials》一书的第一章“Designing for iOS 7”&#xff0c;主要从程序员角度介绍了iOS7的新设计理念&#xff0c;堪称神作&#xff01;本文翻译仅作学习交流之用&#xff0c;版权归原作者所有&#xff0c;有删减。非专业翻译人士粗糙之…

有兴趣的执行一下这段代码

有兴趣的执行一下这段代码&#xff1a;staticpublicstringGetConfigiuageConnString() { Guid dataLinksGuid new Guid("2206cdb2-19c1-11d1-89e0-00c04fd7a829"); Type dataLinksType Type.GetTypeFromCLSID(dataLinksGuid, true); …

python爬虫知识点总结(二十三)Scrapy中Download Middleware的用法

待更新转载于:https://www.cnblogs.com/cthon/p/9424551.html

(C++)输入3个字符串,按从小到大的顺序输出。

#include<cstdio> #include<cstring> //1.利用指针编写两个字符串的比较函数 //2.利用二位字符数组接收3个字符串 //3.输出排序后的字符串 void s_to_b(char str1[10],char str2[10]){char temp[10];strcpy(temp,str1);strcpy(str1,str2);strcpy(str2,temp); }void…

Mysql备份还原数据库之mysqldump实例及参数详细说明

我们在运营项目的过程中肯定会遇到备份数据库&#xff0c;还原数据库的情况&#xff0c;我们一般用一下两种方式来处理&#xff1a; 1.使用into outfile 和 load data infile导入导出备份数据 这种方法的好处是&#xff0c;导出的数据可以自己规定格式&#xff0c;并且导出的是…

女性护理品牌Honeymate获8000万A+轮融资,将与美图公司深度合作

8月5日消息&#xff0c;女性护理品牌“美则Honeymate”于今年7月获美图公司8000万A轮战略融资&#xff0c;资金主要用于品牌扩张以及用户体系、会员体系的建立&#xff0c;也将与美图公司深度合作&#xff0c;为美图超5亿用户创造更多价值。 美则Honeymate&#xff08;深圳市护…

桌面图标不透明的小问题处理

"我的电脑"--"属性"--"高级"--"设置",将下框"在桌面上为图标标签使用阴影"打勾. 在"自定义桌面"里去除相应"桌面网页"项.通过如上两步一般就可以去除图标后面的方框背景, 早上一来遇到位同事问我桌面图…

<论文翻译>RepVGG: Making VGG-style ConvNets Great Again

RepVGG:让VGG风格的卷积网络再一次伟大 文章目录RepVGG:让VGG风格的卷积网络再一次伟大摘要1. Introduction2. Related Work2.1 从单路径到多分支2.2 有效的单路径模型的训练2.3 模型重新参数化2.4 温诺格勒(Winograd)卷积3. 通过结构性重新参数化构建RepVGG3.1 简单就是快&…

关于android布局的两个属性dither和tileMode,background 平铺

http://blog.csdn.net/yuxiaohui78/article/details/8196043转载于:https://www.cnblogs.com/leihupqrst/p/3711725.html

volatile - 如何实现线程安全

2019独角兽企业重金招聘Python工程师标准>>> volatile关键字&#xff0c;在我之前的博客 Volatile - 用途 中已经简单讲解过&#xff0c;当时提出了volatile在多线程中是不安全的。本文将重点介绍一种使用方式&#xff0c;可以实现线程安全。 首先&#xff0c;来看一…

【我翻译的文章】你还需要数据层吗?

随着LINQ的临近发布&#xff0c;独立数据访问层的必要性需要重新进行评估了。它是否仍是应用程序设计的一个重要部分&#xff1f;或者它是否会变成一个过去的附属物&#xff1f; 详细信息请访问&#xff1a;http://www.infoq.com/cn/news/2007/08/DAL转载于:https://www.cnblog…

正则表达式最常用的符号匹配

字符描述\d代表任意数字&#xff0c;就是阿拉伯数字 0-9 这些玩意。\D大写的就是和小写的唱反调&#xff0c;\d 你代表的是任意数字是吧&#xff1f;那么我 \D 就代表不是数字的。\w跟 \w 唱反调&#xff0c;代表不是字母&#xff0c;不是数字&#xff0c;不是下划线的。\n代表…

一道多线程编程题

有意思的一道多线程编程题请用多线程显示&#xff0c;每三个数字为一组&#xff0c;直到30线程A&#xff1a;1线程A&#xff1a;2线程A&#xff1a;3线程B&#xff1a;4线程B&#xff1a;5线程B&#xff1a;6线程A&#xff1a;7线程A&#xff1a;8线程A&#xff1a;9public cla…

垃圾回收机制:

2019独角兽企业重金招聘Python工程师标准>>> 垃圾回收机制&#xff1a; 1、GC通过确定对象是否被活动对象引用来确定是否收集该对象。 2、触发GC的条件 1)GC在优先级最低的线程中运行&#xff0c;一般在应用程序空闲即没有应用线程在运行时被调用。但下面的条件例外…

爬虫入门知识笔记

1.爬虫是什么 定义一&#xff1a; 网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff09;就是模拟浏览器发送网络请求&#xff0c;接收请求响应&#xff0c;一种按照一定的规则&#xff0c;自动地抓取互联网信息的程序。原则上,只要是浏览器(客户端)能做的事…

SQL SERVER中什么情况会导致索引查找变成索引扫描

原文:SQL SERVER中什么情况会导致索引查找变成索引扫描SQL Server 中什么情况会导致其执行计划从索引查找&#xff08;Index Seek&#xff09;变成索引扫描&#xff08;Index Scan&#xff09;呢&#xff1f; 下面从几个方面结合上下文具体场景做了下测试、总结、归纳。 1&…

wait跟sleep的区别

区别 wait sleep 线程 自动唤醒 object的方法只要 线程碰到wait就要等 待不能指定哪个线程等待 Thread的方法 wait用于同步 在任何地方使用 自动释放锁 不会释放锁 转载于:https://www.cnblogs.com/-try/p/3714954.html

AMD真龙一族网络社区成立

AMD成立了一个网络社区&#xff0c;叫"真龙一族"&#xff0c;在各大厂商里这的确为一创新之举&#xff0c;看来AMD对自己的产品确实是非常的有信心。有打算买电脑的人可进去看看&#xff0c;参考一下。地址http://www.longamd.cn/default.htm转载于:https://www.cnbl…

<论文阅读>CascadePSP: Toward Class-Agnostic and Very High-Resolution Segmentation via Global and...

名词解释&#xff1a; 双三次插值&#xff1a;双三次插值是一种更加复杂的插值方式&#xff0c;它能创造出比双线性插值更平滑的图像边缘。 **标题翻译&#xff1a;**通过全局和局部优化进行面向不可知类和超高像素图像的分割 CascadePSP: Toward Class-Agnostic and Very Hig…

【转】MYSQL入门学习之十:视图的基本操作

转载地址&#xff1a;http://www.2cto.com/database/201212/176775.html 一、视图的基本介绍 www.2cto.com 视图是虚拟的表。与包含数据的表不一样&#xff0c;视图只包含使用时动态检索数据的查询。使用视图需要MySQL5及以后的版本支持。下面是视图的一些常见应用&#xff1…

自动化运维之SaltStack,批量安装httpd实战

SaltStack原理 SaltStack由Master和Minion构成&#xff0c;Master 是服务端&#xff0c; 表示一台服务器&#xff1b;Minion是客户服务端&#xff0c;表示多台服务器。在Master上发送命令给符合条件的Minion,Minin就会执行相应的命令&#xff0c;Master和Minion之间是通过ZeroM…

我的面试(四)补充1

突然想起来前天面试时&#xff0c;考官问我out参数和ref参数的区别。我当时答的是out是出的&#xff0c;ref可以来回传参。也就是说out参数是进不来的&#xff0c;而ref是可以进来了。今天写代码试了试。从新整理一下关于out和ref的区别。static void Function1(out int outPar…

(C++)输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。要求用3个函数实现,分别为输入10个数、进行处理、输出10个数。要求使用指针的方法进行处理。

#include<cstdio> //输入10个整数&#xff0c;将其中最小的数与第一个数对换&#xff0c;把最大的数与最后一个数对换。要求用3个函数实现&#xff0c;分别为输入10个数、进行处理、输出10个数。要求使用指针的方法进行处理。 //编写函数——输入10个数 //编写函数——进…

深入biztalk消息以及消息订阅发布路由机制(二)-消息订阅【转】

一.消息订阅 订阅消息的主体叫订阅服务器&#xff0c;订阅服务器是可以订阅并消费消息的服务&#xff0c;可以作为订阅服务器的服务类型目前有四类&#xff0c;在BizTalkMgmtDb管理数据库中的adm_ServiceClass的Name字段列出了所有可以作为订阅服务器的服务类型&#xff0c;包括…