C#:多线程Task使用
一.Task与Thread
- Task是架构在Thread之上的,也就是说任务最终还是要抛给线程去执行。
- Task跟Thread不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制。
Task
是用于表示一个异步操作的抽象。它是一种轻量级的、可等待的对象,允许你在不阻塞当前线程的情况下执行操作- Task用途:可以用来处理各种耗时的操作,如文件I/O、网络请求、复杂的计算等,从而提高应用程序的响应性和性能。例如,在一个图形用户界面(GUI)应用程序中,使用
Task
来执行长时间的文件读取操作,这样在读取文件时,用户界面仍然可以响应用户的其他操作,如点击按钮、移动窗口等 - Task为后台程序,前台程序执行完毕后,软件即可结束
二.Task是使用方法:
创建Task,无返回值的创建方法,使用Task 创建以及使用Lambda表达式创建:有返回值的创建方法,Task支持泛型编程
//方法一:
Task b = new Task(()=> Console.WriteLine( "Task 2" ));
b.start;
//方法二
Task.Run(() =>
{Console.WriteLine("Task1");
});
//方法三:TaskFactory taskFactory = new TaskFactory();taskFactory.StartNew(() => { Console.WriteLine("工厂模式创建"); });//有返回值
Task<int> taskWithResult = Task.Run(() =>
{return 42; // 返回一个整数结果
});
Console.WriteLine(taskWithResult.Result);
执行结果,Task创建的为后台程序,当主线程为前台程序,当前台程序执行完毕,程序结束,后台程序会出现没有执行的情况:
Task1
工厂模式创建
Task 2
42
使用以下程序进行测试:
static void Main(string[] args)
{Task.Run(() =>{Console.WriteLine("Task1");});TaskFactory taskFactory = new TaskFactory();taskFactory.StartNew(() => { Console.WriteLine("工厂模式创建"); });///Task a =new Task(program.GetTicket);Task b = new Task(()=> Console.WriteLine( "Task 2" ));b.Start();Console.WriteLine( "main主程序" );
}
执行结果如下:
//执行结果1:
main主程序
Task1
工厂模式创建
Task 2//执行结果2:
main主程序
工厂模式创建
Task1
为了解决这个问题,Task提供一系列API进行线程控制:
Task API | 意义 |
---|---|
Task.Result | 获取Task的返回值 |
Task.ContinueWith | 一个任务完成后执行 |
Task.Delay | 异步延迟程序,不会阻碍主线程 |
Task.Wait | 用与阻塞当前线程,直到指定任务完成,相当于Thread.Join() |
Task.WaitAll | 等待列表中的任务全部完成,传递Array |
Task.WaitAny | 等待列表中的任一任务全部完成,传递Array |
Task.WhenAll | 等待列表中的任务都完成(异步),传递Array |
Task.WhenAny | 等待列表中的任一任务完成(异步),传递Array |
通过程序逐步演示该API使用方法:
Task task1 = new Task(()=> Console.WriteLine("Task1"));
Task task2 = task1.ContinueWith(t => //t和task1为同一任务{Console.WriteLine(t ==task1);Console.WriteLine("task2");});task1.Start();// task2.Start();//持续线程不可以使用starttask1.Wait(); //阻塞主线程,Task线程完成后在进行执行task2.Wait(); //阻塞主线程,Task线程完成后在进行执行Console.WriteLine( "main线程" );
打印结果:
Task1
True
task2
main线程
- Continue with使用,参数t指的是上一个Task:
Task<int> task1 = Task.Run(() =>{return 10086;Console.WriteLine("Task1 is Running"); } );Task<int> task2 = task1.ContinueWith(t => { return t.Result + 1;Console.WriteLine("Task2 is Running");});Task<int> task3 = task2.ContinueWith(t => {return t.Result + 1;Console.WriteLine("Task2 is Running");});Console.WriteLine( task3.Result );Console.WriteLine( task1.Result );Console.WriteLine( task2.Result );
打印结果:
10088
10086
10087
三.async和await:
async执行一个异步方法,await执行一个异步任务,当程序遇见await会单独开一个控制流,不影响主线程的执行。
static void Main(string[] args){Console.WriteLine($"main方法Begins:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");RunAsync();Console.WriteLine($"main方法Ends:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");Console.ReadLine();
}public static async void RunAsync() //异步方法必须使用async
{Console.WriteLine( $"RunAsync方法Begin:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}" );//await开启异步任务await Task.Run(() =>{Console.WriteLine($"Task方法Begin:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");long sum = 0;for (long i = 0; i < 10000000000; i++) {sum += i;};Console.WriteLine();Console.WriteLine($"Task方法End:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");});Console.WriteLine($"RunAsync方法End:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");}
打印结果:
main方法Begins:线程ID:1,是否在线程池False
RunAsync方法Begin:线程ID:1,是否在线程池False
main方法Ends:线程ID:1,是否在线程池False
Task方法Begin:线程ID:3,是否在线程池TrueTask方法End:线程ID:3,是否在线程池True
RunAsync方法End:线程ID:3,是否在线程池True
使用async和await执行有返回值的方法,异步任务的返回值类型默认为Task,await作用有两个,分流和获取任务返回值的功能,没有await关键字,则相当于同步方法:
static void Main(string[] args){Console.WriteLine($"main方法Begins:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");RunAsync();Console.WriteLine($"main方法Ends:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");Console.ReadLine();
}public static async void RunAsync()
{long result=await GetSumAsync(); //必须使用await,getsum是任务,异步分流Console.WriteLine($"计算结果是:{result}");
}
public static async Task<long> GetSumAsync()
{return await Task.Run(() =>{long sum = 0;for (long i = 0; i < 1000000000; i++){sum += i;}return sum; });
}
打印结果:
main方法Begins:线程ID:1,是否在线程池False
main方法Ends:线程ID:1,是否在线程池False
计算结果是:499999999500000000
相关文章:
C#:多线程Task使用
一.Task与Thread Task是架构在Thread之上的,也就是说任务最终还是要抛给线程去执行。Task跟Thread不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制。…...

模拟电子技术基础----绪论
一、电子技术的发展 1.电子技术的发展,推动计算机技术的发展,使之“无孔不入”,应用广泛! •广播通信:发射机、接收机、扩音、录音、程控交换机、电话、手机 •网络:路由器、ATM交换机、收发器、调制解调…...
从零基础到最佳实践:Vue.js 系列(2/10):《模板语法与数据绑定》
Vue.js 模板语法与数据绑定:从基础到实践 关键点 Vue.js 的模板语法使用 HTML 结合特殊指令(如 v-bind、v-on),实现动态界面。插值({{ }})显示数据,指令控制 DOM 行为,双向绑定简化…...

iOS 使用 - 设置 来电震动/关闭震动
来电震动是一个很直观的老功能。但到了iOS 18,苹果却把震动功能的开关藏得越来越深,甚至分散在不同的菜单里,让用户难以找到。这里记录分享设置方法: 1. 震动开关的路径 设置 → 通用 → 辅助功能 → 触控 → 震动 2. 来电震动…...
anaconda、miniconda、conda的关系及miniconda安装
anaconda、miniconda、conda的关系及miniconda安装 文章目录 前言正文定义关系Linux安装miniconda新建一个python3.8环境 参考 前言 本文用于记录关于Anaconda、conda和Miniconda的定义及其关系的总结123: 正文 定义 conda 一个跨平台的开源包管理和环境管理工具…...

[C语言初阶]扫雷小游戏
目录 一、原理及问题分析二、代码实现2.1 分文件结构设计2.2 棋盘初始化与打印2.3 布置雷与排查雷2.4 游戏主流程实现 三、后期优化方向 在上一篇文章中,我们实现了我们的第二个游戏——三子棋小游戏。这次我们继续结合我们之前所学的所有内容,制作出我们…...

谷歌medgemma-27b-text-it医疗大模型论文速读:多语言大型语言模型医学问答基准测试MedExpQA
《MedExpQA: 多语言大型语言模型医学问答基准测试》论文解析 一、引言 论文开篇指出大型语言模型(LLMs)在医学领域的巨大潜力,尤其是在医学问答(QA)方面。尽管LLMs在医学执照考试等场景中取得了令人瞩目的成绩&#…...
Lambda表达式的高级用法
今天来分享下Java的Lambda表达式,以及它的高级用法。 使用它可以提高代码的简洁度,使代码更优雅。 一、什么是lambda表达式 Lambda 表达式是 Java 8 引入的特性,用于简化匿名内部类的语法,使代码更简洁,尤其在处理函…...
速盾(sudun):如何利用CDN技术实现页面加速?
随着互联网内容的爆炸式增长,用户对网页加载速度的要求也越来越高。快速加载的网页不仅能提升用户体验,还能直接影响搜索引擎排名和网站转化率。内容分发网络(CDN)作为一种有效的解决方案,通过在全球范围内部署多个高性…...

DeepSeek+白果AI论文:开启答辩PPT生成的「智能双引擎」时代
2025学术答辩革新:DeepSeek与白果AI论文的黄金协同方案 白果Ai论文,论文写作神器~ https://www.baiguoai.com/ 在学术答辩的「战场」上,「选题创新不足」「数据可视化低效」「PPT逻辑断裂」等痛点长期困扰研究者。DeepSeek与白果AI论文的深…...
Jest入门
快速入门 Jest中文文档 | Jest中文网 1.下载:npm install --save-dev jest 2.创建 sum.js 文件: function sum(a, b) { return a b; } module.exports sum; 3.创建sum.test.js 的文件 const sum require(./sum); test(adds 1 2 to equal 3,…...

SDC命令详解:使用set_logic_dc命令进行约束
相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 set_logic_dc命令可以将当前设计中的输入端口为不关心(设置端口的driven_by_dont_care属性为true),该端口在综合是可以被认为是…...

小程序涉及提供提供文本深度合成技术,请补充选择:深度合成-AI问答类目
一、问题描述 最近新项目AI咨询小程序审核上线,按照之前小程序的流程,之前审核,提示审核不通过,审核不通过的原因:小程序涉及提供提供文本深度合成技术 (如: AI问答) 等相关服务,请补充选择:深…...
SQL每日一练(2)
表: 产品表 p product_idproduct_name1产品 A2产品 B3产品 C 销售表 s sale_idproduct_idcountryamountsale_date11法国1000.002020-09-1522法国1500.002020-09-2033法国800.002020-09-1041英国1200.002020-09-2552英国1600.002020-09-0563英国900.002020-09-30…...

基于亚博K210开发板——lvgl 图形化实验
开发板 亚博K210开发板 实验目的 本次测试主要学习 K210 图形化操作界面的功能。 实验元件 LCD 显示屏、FT6236 触摸板 lvgl 图形化库简介 LVGL(轻度综合图形界面库)是一个免费开源图形库,具有使用方便,画面美观ÿ…...

LABVIEW 通过节点属性动态改变数值显示控件的方法
在 LabVIEW 里,能够借助属性节点来改变数值输入控件的禁用状态。下面为你介绍具体的操作步骤: 1. 创建或开启前面板 要先创建一个数值输入控件,操作方法是:点击 "控件" 选板,接着选择 "新式→数值→数…...

信息安全管理与评估2025上海卷
上海市“星光计划”第十一届职业院校技能大赛 (高职组) “信息安全管理与评估”赛项 任务书 一、 赛项时间共计4小时。二、 赛项信息 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 平台搭建与安全设备 配置防护 任务1 网络平台搭建 2…...
el-form 使用el-row el-col对齐 注意事项
1.el-form 使用inline,el-form-item宽度会失效。 2.为了保证el-form-item 和 它内部的el-input 能在一行,要设置el-form-item的label-width <el-form :model"editInspectform"><el-row style"margin-bottom: 20px"><…...
使用Terraform创建azure databrick
Azure Databricks 介绍 Azure Databricks是一种在Microsoft Azure云平台上运行的快速、易于使用的分析和大数据处理服务。它是基于Apache Spark的分析平台,可帮助用户以更高效的方式进行数据处理、数据分析和机器学习任务。Azure Databricks提供了一个协作式的工作环境,使数…...
Python爬虫开发基础案例:构建可复用的名言采集系统
一、项目背景与技术选型 1.1 爬虫技术应用场景 网络爬虫作为数据采集的核心技术,在舆情监控、价格比对、学术研究等领域发挥着重要作用。本案例选择quotes.toscrape.com作为目标网站,因其具有以下典型特征: 公开允许爬取的测试环境清晰的H…...
Spring Boot 中修改 HTTP 响应状态码(即 `response.status`)可以通过以下几种方式实现
以下是不同场景下的具体方法: 方法 1:直接使用 ResponseStatus 注解 在 Controller 方法或异常类上使用 ResponseStatus 注解,直接指定返回的状态码。 场景示例:固定返回指定状态码 import org.springframework.http.HttpStatu…...

Linux目录介绍+Redis部署(小白篇)
目录 👑Linux基础✨【目录】 👑Redis 安装1.下载压缩包2.解压3.安装编译环境4.安装到本地5.设置开机自启 👑Linux 自启服务 👑Linux基础 虽然在大二的时候学过Linux,但是很多基础知识都忘了,想再次从基础捡…...
软件开发MVC三层架构杂谈
在当今的软件开发领域,MVC(Model-View-Controller)架构已成为构建复杂系统时不可或缺的设计模式。它通过将应用程序划分为模型(Model)、视图(View)和控制器(Controller)三…...

Python 基础语法速查手册:从入门到精通
Python 作为最受欢迎的编程语言之一,以其简洁易读的语法和强大的功能吸引了大量开发者。本文全面汇总 Python 基础语法知识,帮助初学者快速掌握核心概念,并为后续深入学习打下坚实基础。 1. Python 基础语法结构 1.1 代码结构与缩进规则 Py…...
Spring框架--IOC技术
一、Spring框架的介绍 1、Spring框架的概述 Spring 是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003年兴起的一个轻量级的Java开发框架,由 Rod Jo…...
前端vue2-完全前端生成pdf->pdf-lib,html2canvas+jspdf,原生打印,三种方式(打印带有echarts图的pdf)
pdf-lib:优点是可以控制输出内容,缺点是麻烦 html2canvas:优点是直接把html页面转成图片之后插入pdf很方便,不用过多的代码,缺点是不好控制图片大小,容易被戒断,可以把想打印的内容藏在页面外面…...

论文阅读笔记——Emerging Properties in Unified Multimodal Pretraining
BAGEL 论文 商业闭源系统与学术/开源模型的差距很大,BAGEL 旨在通过开源统一架构大规模交错数据主要解决: 架构割裂:理解/生成分属两条网络,信息被压缩在少量条件 token 中,长上下文推理受限。数据贫乏:主…...

JAVA批量发送邮件(含excel内容)
EmailSenderHtmlV1 是读取配置文件《批量发送邮件.xlsx》,配置sheet获取 发件人邮箱 邮箱账号 口令,发送excel数据sheet获取收件人邮箱 抄送人邮箱 邮件标题 第N行开始(N>1,N0默认表头) 第M行结束(M>1,M0默认表头) 附件文件夹…...

Linux(Ubuntu)新建文件权限继承问题
当你在一个工作目权限为777的文件下,新建一个文件的时候,就有可能发生,新建的这个文件,权限和其他文件,或者工作目录不一致的问题,我们不可能每次新建一个文件,就要 sudo chmod -R 777 /PATH 所…...

Java中的String的常用方法用法总结
1.1 String (1)声明 (2)字符串常量 存储字符串数据的容器:private final char value[] 字符串常量都存储在字符串常量池(StringTable)中 字符串常量池不允许存放两个相同的字符串常量 ÿ…...