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

C# .Net学习笔记—— 异步和多线程(Task)

一、概念

Task是DotNet3.0之后所推出的一种新的使用多线程的方式,它是基于ThreadPool线程进行封装的。

二、使用多线程的时机

任务能够并发运行的时候,提升速度;优化体验

三、基本使用方法

        private void button5_Click(object sender, EventArgs e){Log.Info($"Task Start {Thread.CurrentThread.ManagedThreadId.ToString("00")}  {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");Task.Run(() => this.DoSomethingLong("BtnTask_Click1"));Task.Run(() => this.DoSomethingLong("BtnTask_Click2"));Log.Info($"Task End {Thread.CurrentThread.ManagedThreadId.ToString("00")}  {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");}private void DoSomethingLong(string name){Log.Info($"DoSomethingLong Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {name} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");long result = 0;for (int i = 0; i < 10000000; i++){result += i;}Thread.Sleep(2000);Log.Info($"DoSomethingLong End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {name} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");}

方法一:

Task.Run(() => this.DoSomethingLong("BtnTask_Click1"));

方法二(这种方式是在DotNet4.0之后出现的):

TaskFactory taskFactory = Task.Factory;
taskFactory.StartNew(() => this.DoSomethingLong("btnTask_Click3"));

方法三:

new Task(() => this.DoSomethingLong("btnTask_Click4")).Start();

四、小案例

题目:现在我有一个项目,产品经理负责提需求,设计产品(主线程)。五位同学分别执行策划、前端、后端、数据库、服务器(子线程)。等所有工作完成后(所有子线程运行结束),再通知甲方过来验收

       //什么时候用多线程?//任务能并发进行;private void button7_Click(object sender, EventArgs e){List<Task> taskList = new List<Task>();Log.Info($"项目经理启动一个项目...{Thread.CurrentThread.ManagedThreadId.ToString("00")}");Log.Info($"前置的准备工作...{Thread.CurrentThread.ManagedThreadId.ToString("00")}");Log.Info($"开始变成...{Thread.CurrentThread.ManagedThreadId.ToString("00")}");taskList.Add(Task.Run(() => this.Coding("周同学", "负责策划")));taskList.Add(Task.Run(() => this.Coding("黄同学", "负责前端")));taskList.Add(Task.Run(() => this.Coding("林同学", "负责后端")));taskList.Add(Task.Run(() => this.Coding("陈同学", "负责数据库")));taskList.Add(Task.Run(() => this.Coding("陈同学", "负责服务器")));//会阻塞当前线程,等着某个任务完成后才进行下一行,卡界面Task.WaitAny(taskList.ToArray());Log.Info($"已经有一个人完成了...{Thread.CurrentThread.ManagedThreadId.ToString("00")}");//多线程加快速度,但是全部任务完成后才能执行的操作Task.WaitAll(taskList.ToArray()); //会阻塞当前线程,等着全部任务完成后,才会进入下一行,卡界面Log.Info("告诉甲方验收,上线使用");//Task.WhenAny(taskList.ToArray()).ContinueWith(t =>//{//    Log.Info($"哈哈哈哈我第一个做完了...{Thread.CurrentThread.ManagedThreadId.ToString("00")}");//});//Task.WhenAll(taskList.ToArray()).ContinueWith(t =>//{//    Log.Info($"部署环境,联调测试...{Thread.CurrentThread.ManagedThreadId.ToString("00")}");//});}private void Coding(string name, string task){Log.Info($"Coding {name} Start {task} 线程号:{Thread.CurrentThread.ManagedThreadId.ToString("00")}  时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");long result = 0;for (int i = 0; i < 1000000000; i++){result += i;}Log.Info($"Coding {name} End {task} 线程号:{Thread.CurrentThread.ManagedThreadId.ToString("00")}  时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");}

知识点:

1、这里Task.WaitAll()会阻塞当前线程,等着全部任务完成后才会继续下一行。这种方式会卡界面

2、Task.WaitAll()第二个参数也可以带参,限时等待

3、Task.WaitAny(taskList.ToArray()) ; 会阻塞当前线程,等着某个任务完成后才进行下一行,卡界面

 WaitAll的使用时机(以某宝为例):

一个业务查询操作有多个数据源,首页-多线程并发-拿到全部数据后才能返回

WaitAny的使用时机(以某宝为例):

一个商品搜索有多个数据源,商品搜索-多个数据源-多线程并发-只需要一个结果即可

WaitAll和WaitAny都是阻塞方法,需要完成后再继续,这会导致卡界面 

 WhenAll和WhenAny是非阻塞方法,不会导致卡界面

 五、控制最大线程的并发数量

       private void button8_Click(object sender, EventArgs e){Log.Info($"Coding Start 线程号:{Thread.CurrentThread.ManagedThreadId.ToString("00")}  时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");ThreadPool.SetMinThreads(8, 8);for (int i = 0; i < 100; i++){Task.Run(() => {Log.Info($"{Thread.CurrentThread.ManagedThreadId.ToString("00")}");Thread.Sleep(2000);});}}

这里通过SetMaxThreads去控制最大的线程并发数量,这种方法并不好,因为ThreadPool是全局的。下面写一种比较合适的方法(用10个线程完成1万个任务):

            {//用10个线程完成1万个任务List<int> list = new List<int>();for (int i = 0; i < 10000; i++){list.Add(i);}Action<int> action = i =>{Log.Info($"{Thread.CurrentThread.ManagedThreadId.ToString("00")}");Thread.Sleep(new Random().Next(100, 300));};List<Task> taskList = new List<Task>();//这里先启动任务foreach (var i in list){int k = i;taskList.Add(Task.Run(() => action.Invoke(k)));//判断个数if (taskList.Count > 10){//这里开始等着Task.WaitAny(taskList.ToArray());//等到某个线程完成后,把还没完成的留着,已完成的清掉。//这样就可以完成对数量的控制taskList = taskList.Where(t => t.Status != TaskStatus.RanToCompletion).ToList();}}Task.WhenAll(taskList.ToArray());}

 六、Task任务添加标识

方法一:TaskFactory的StartNew方法可以有一个重载,传入state作为标识

可以看到在Task任务结束后,通过AsyncState可以打印出我们的标识。这种方式我们就可以知道是谁先完成的

方法二:Task方法并没有直接使用的API来传递一个标识,

 七、Task回调

t指的是参数2,回调写到t=>{}里面

Task.Run(()=>this.Coding("哈哈哈","参数2")).ContinueWith(t=>{});

 八、延迟和等待

Task.Delay(1000);//延迟  不会卡
Thread.Sleep(1000);// 等待 卡

  九、Parallel

1、基本介绍:Parallel是基于Task封装的,并行编程。在4.5以后版本出现

2、三种启动方式:

 private void button10_Click(object sender, EventArgs e){Log.Info($"Coding Start 线程号:{Thread.CurrentThread.ManagedThreadId.ToString("00")}  时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");{//启动方式一:Parallel.Invoke(() => this.Coding("哇哈哈", "whh"),()=>this.Coding("啦啦啦", "lll"),()=>this.Coding("哦哦哦", "ooo"),()=>this.Coding("呸呸呸", "ppp"));}{//启动方式二://Parallel.For(0, 5, i => this.Coding("哈哈哈", "Client" + i));}{//启动方式三:Parallel.ForEach(new string[] { "0", "1", "2" ,"3","4"}, i => this.Coding("哈哈哈", "Client" + i));}Log.Info($"Coding End 线程号:{Thread.CurrentThread.ManagedThreadId.ToString("00")}  时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");}

3、限制线程数,用3个线程完成10个任务

   ParallelOptions parallelOptions = new ParallelOptions();parallelOptions.MaxDegreeOfParallelism = 3;Parallel.For(0, 5, parallelOptions, i => this.Coding("哈哈哈", "Client" + i));

这样得出的结果,任意时刻都只有3个线程在工作

4、不卡的方式,用Task再包一层

           Task.Run(() => {ParallelOptions parallelOptions = new ParallelOptions();parallelOptions.MaxDegreeOfParallelism = 3;Parallel.For(0, 5, parallelOptions, i => this.Coding("哈哈哈", "Client" + i));});

 5、线程结束 

相关文章:

C# .Net学习笔记—— 异步和多线程(Task)

一、概念 Task是DotNet3.0之后所推出的一种新的使用多线程的方式&#xff0c;它是基于ThreadPool线程进行封装的。 二、使用多线程的时机 任务能够并发运行的时候&#xff0c;提升速度&#xff1b;优化体验 三、基本使用方法 private void button5_Click(object sender, Ev…...

Python从入门到网络爬虫(读写Excel详解)

前言 Python操作Excel的模块有很多&#xff0c;并且各有优劣&#xff0c;不同模块支持的操作和文件类型也有不同。最常用的Excel处理库有xlrd、xlwt、xlutils、xlwings、openpyxl、pandas&#xff0c;下面是各个模块的支持情况&#xff1a; 工具名称.xls.xlsx获取文件内容写入…...

Mysql之子查询、连接查询(内外)以及分页查询

目录 一.案例&#xff08;接上篇博客&#xff09; 09&#xff09;查询学过「张三」老师授课的同学的信息 10&#xff09;查询没有学全所有课程的同学的信息 11&#xff09;查询没学过"张三"老师讲授的任一门课程的学生姓名 12&#xff09;查询两门及其以上不及格课程…...

计算机的存储单位

在计算机中&#xff0c;只能识别二进制。 byte是1个字节&#xff0c;是8个比特位&#xff0c;所以byte可以存储的最大值是&#xff1a;01111111&#xff0c;byte是 [-128 ~ 127] 共可以标识256个不同的数字。 1字节 8bit&#xff08;8比特&#xff09;--> 1byte 8bit 类…...

设备树文件中的设备节点

一. 简介 前面几篇文章学习了 关于设备树文件的编译&#xff0c;设备树文件的调用。 本文开始学习 设备树文件的语法。具体学习设备节点与标准属性。 二. 设备树文件之设备节点与标准属性 1. 设备节点 设备树 是采用树形结构来描述板子上的设备信息的文件&#xff0c;每…...

文件管理工具.netcore资源文件管理

文件管理工具 怎么快速有效的管理我的文件包括文件夹&#xff0c;需求功能是 模糊搜索显示匹配的文件夹或文件数据 快速打开文件夹位置 在windows直接查看搜索速度太慢&#xff0c;范围宽泛&#xff0c;整理所需资源文件名和文件本机路径保存在数据库&#xff0c;可以在数据库中…...

go-carbon v2.3.4 发布,轻量级、语义化、对开发者友好的 Golang 时间处理库

carbon 是一个轻量级、语义化、对开发者友好的 golang 时间处理库&#xff0c;支持链式调用。 目前已被 awesome-go 收录&#xff0c;如果您觉得不错&#xff0c;请给个 star 吧 github.com/golang-module/carbon gitee.com/golang-module/carbon 安装使用 Golang 版本大于…...

vue3 内置组件

文章目录 前言一、过渡效果相关的组件1、Transition2、TransitionGroup 二、状态缓存组件&#xff08;KeepAlive&#xff09;三、传送组件&#xff08;Teleport &#xff09;四、异步依赖处理组件&#xff08;Suspense&#xff09; 前言 在vue3中 其提供了5个内置组件 Transiti…...

MFC如何动态创建button按钮并添加点击事件

在MFC中&#xff0c;可以使用CButton类来动态创建按钮。下面是一个示例代码&#xff0c;演示了如何动态创建按钮并添加点击事件&#xff1a; 在对话框类的头文件中声明按钮变量&#xff1a; CButton m_btnDynamic;在对话框的OnInitDialog()函数中使用Create()函数创建按钮&am…...

Qt - QML框架

文章目录 1 . 前言2 . 框架生成3 . 框架解析3.1 qml.pro解析3.2 main.cpp解析3.3 main.qml解析 4 . 总结 【极客技术传送门】 : https://blog.csdn.net/Engineer_LU/article/details/135149485 1 . 前言 什么是QML&#xff1f; QML是一种用户界面规范和编程语言。它允许开发人员…...

Python+Flask+MySQL的图书馆管理系统【附源码,运行简单】

PythonFlaskMySQL的图书馆管理系统【附源码&#xff0c;运行简单】 总览 1、《的图书馆管理系统》1.1 方案设计说明书设计目标需求分析工具列表 2、详细设计2.1 登录2.2 注册2.3 程序主页面2.4 图书新增界面2.5 图书信息修改界面2.6 普通用户界面2.7 其他功能贴图 3、下载 总览…...

Module-Federation[微前端]

Module-Federation 微前端简介我们为什么没有延续使用【乾坤】使用Module-Federation 优/缺EMP 优EMP 缺图解DEMO详解`Tips:` [文件资源](https://download.csdn.net/download/alnorthword/88699315)微前端简介 微前端是借鉴了微服务的理念,将一个庞大的应用拆分成多个独立灵活…...

Spring 动态数据源事务处理

在一般的 Spring 应用中,如果底层数据库访问采用的是 MyBatis,那么在大多数情况下,只使用一个单独的数据源,Spring 的事务管理在大多数情况下都是有效的。然而,在一些复杂的业务场景下,如需要在某一时刻访问不同的数据库,由于 Spring 对于事务管理实现的方式,可能不能达…...

WSL2-Ubuntu22.04子系统图形化界面搭建与远程桌面连接

提示&#xff1a;文中不提供WSL2子系统搭建步骤&#xff0c;假定子系统已建立好&#xff1a; 文章目录 检查WSL子系统状态图形化界面安装远程桌面连接可能遇到的相关问题xrdp状态异常远程桌面黑屏 检查WSL子系统状态 wsl -l -v如下图所示为正常 图形化界面安装 以此执行如下…...

【sklearn练习】model常用属性和功能

介绍 scikit-learn 中的机器学习模型&#xff08;estimator&#xff09;通常具有一组常用属性和功能&#xff0c;这些属性和功能可以用于训练、评估和使用模型。以下是一些常见的模型属性和功能&#xff1a; 常见属性&#xff1a; coef_&#xff1a;对于线性模型&#xff08;…...

IO类day01

File类 File类的每一个实例可以表示硬盘(文件系统)中的一个文件或目录(实际上表示的是一个抽象路径) 使用File可以做到: 1:访问其表示的文件或目录的属性信息,例如:名字,大小,修改时间等等 2:创建和删除文件或目录 3:访问一个目录中的子项 但是File不能访问文件数据. pu…...

软件测试大作业||测试计划+测试用例+性能用例+自动化用例+测试报告

xxx学院 2023—2024 学年度第二学期期末考试 《软件测试》&#xff08;A&#xff09;试题&#xff08;开卷&#xff09; 题目&#xff1a;以某一 web 系统为测试对象&#xff0c;完成以下文档的编写&#xff1a; &#xff08;满分 100 分&#xff09; &#xff08;1&am…...

适用于任何公司的网络安全架构

1.第一等级:基础级 优势 可防范基本有针对性的攻击&#xff0c;使攻击者难以在网络上推进。将生产环境与企业环境进行基本隔离。 劣势 默认的企业网络应被视为潜在受损。普通员工的工作站以及管理员的工作站可能受到潜在威胁&#xff0c;因为它们在生产网络中具有基本和管理…...

Excel:通过excel将表数据批量转换成SQL语句

这里有一张表《student》&#xff0c;里面有10条测试数据&#xff0c;现在将这10条测试数据自动生成 insert语句&#xff0c;去数据库 批量执行 P.S. 主要用到excel表格中的 CONCATENATE函数&#xff0c;将单元格里面的内容填入到sql里面对应的位置 1. 先写好一条insert语句&a…...

Android linphone-android sdk设置语音编码问题

1.遇到的问题 今天遇到linphone-android sdk需要解决语音编码问题&#xff0c;需要指定编码。查了下配置&#xff0c;里面没有发现类似的配置。 ## Start of factory rc # This file shall not contain path referencing package name, in order to be portable when app is r…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)

Name&#xff1a;3ddown Serial&#xff1a;FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名&#xff1a;Axure 序列号&#xff1a;8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...

Qt的学习(一)

1.什么是Qt Qt特指用来进行桌面应用开发&#xff08;电脑上写的程序&#xff09;涉及到的一套技术Qt无法开发网页前端&#xff0c;也不能开发移动应用。 客户端开发的重要任务&#xff1a;编写和用户交互的界面。一般来说和用户交互的界面&#xff0c;有两种典型风格&…...

echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式

pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图&#xff0c;如果边框加在dom上面&#xff0c;pdf-lib导出svg的时候并不会导出边框&#xff0c;所以只能在echarts图上面加边框 grid的边框是在图里…...

qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001

qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类&#xff0c;直接把源文件拖进VS的项目里&#xff0c;然后VS卡住十秒&#xff0c;然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分&#xff0c;导致编译的时候找不到了。因…...