C# Task任务详解
文章目录
- 前言
- Task
- 返回值
- 无参返回
- 有参返回
- async和await
- 返回值
- await搭配使用
- Main async改造
- Task进阶
- Task线程取消
- 测试用例
- 超时设置
- 线程暂停和继续
- 测试用例
- 多任务等最快
- 多任务全等待
- 结论
前言
Task是对于Thread的封装,是极其优化的设计,更加方便了我们如何操控线程
Task
Task声明形如:
public static Task Sleep()
{}
Task是一种类型
返回值
直接声明Task是需要返回值的。
无参返回
public static Task Sleep(int second)
{return Task.CompletedTask;
}
有参返回
public static Task<T> Sleep(){return Task.FromResult(T);}
//举例,返回参数只能唯一,除非使用元祖public static Task<string> Sleep(){return Task.FromResult("Hello world!");}
使用Task.Result获取返回值
var res = Sleep().Result;
async和await
async和await是对于异步事件的控制,方便我们对异步事件的操控。
返回值
使用async之后可以直接设置返回值
///有参返回public static async Task<string> Sleep(){return "Hello world";}///无参返回public static async Task Sleep(){}
await搭配使用
异步事件的等待使用await方法
public static async Task Sleep(int second){await Task.Delay(second * 1000);Console.WriteLine($"等待{second}s");}static void Main(string[] args){Sleep(3);Sleep(2);Sleep(1);Console.WriteLine("运行完毕");//使用键盘键入事件阻塞主进程,主进程结束程序会立即退出Console.ReadKey();}
打印结果:
打印结果显示:
- 同步事件先结束
- 异步事件互相不阻塞,3,2,1同时开始,等待3,2,1s打印1,2,3。
Main async改造
主程序是Void,无法等待
将Void改成Task,即可等待异步事件
打印结果服务预期,等待异步事件结束后运行
Task进阶
C#Task取消任务执行CancellationTokenSource
C# Task 暂停与取消
Task线程取消
以前Thread有Abort()方法,强行销毁线程,但是这个方法用于极大的安全问题,已经被弃用。
线程不能直接被销毁,只能通过抛出异常来取消线程。
//声明token
var tokenSource = new CancellationTokenSource();
//注册异常抛出
tokenSource.Token.ThrowIfCancellationRequested();
//注册取消事件回调
tokenSource.Token.Register(() =>
{Console.WriteLine("线程已被取消");
});。。。。。。别的地方的代码
//取消token,那么之前写ThrowIfCancellationRequested的地方会直接结束
tokenSource.Cancel();
测试用例
一个简单的死循环函数,运行时返回token,用于直接跳出程序
static async Task Main(string[] args)
{var token = Loop();//等待3s抛出异常await Task.Delay(1000 * 3);Console.WriteLine("任务完成!");token.Cancel();Console.ReadKey();}/// <summary>
/// 循环等待
/// </summary>
/// <returns></returns>
public static CancellationTokenSource Loop()
{var tokenSource = new CancellationTokenSource();Console.WriteLine("任务开始!");tokenSource.Token.Register(() =>{Console.WriteLine("线程已被取消");});var count = 0;Task.Run(async () =>{while (true){await Task.Delay(1000);//抛出异常,直接结束线程tokenSource.Token.ThrowIfCancellationRequested();count++;Console.WriteLine(count);}});return tokenSource;
}
打印结果
这样使用起来也更加安全。
超时设置
tokenSource.CancelAfter是超时方法。
CancelAfter(1000):1000毫秒后超时
static async Task Main(string[] args){var token = Loop();///3000毫秒后取消token.CancelAfter(1000*3);Console.ReadKey();}/// <summary>/// 循环等待/// </summary>/// <returns></returns>public static CancellationTokenSource Loop(){var tokenSource = new CancellationTokenSource();Console.WriteLine("任务开始!");tokenSource.Token.Register(() =>{Console.WriteLine("线程已被取消");});var count = 0;Task.Run(async () =>{while (true){await Task.Delay(1000);tokenSource.Token.ThrowIfCancellationRequested();count++;Console.WriteLine(count);}});return tokenSource;}
线程暂停和继续
线程暂停也是使用一个类去控制,ManualResetEvent。和线程销毁一样,是不能直接暂停的,因为直接暂停也不安全。
//声明,false为默认阻塞,true为不阻塞
var resetEvent = new ManualResetEvent(false);
//暂停,通过WaitOne方法来阻塞线程,通过Set和Reset来设置是否阻塞
resetEvent.WaitOne();
//阻塞暂停
resetEvent.Set()
//取消阻塞,继续
resetEvent.Reset()
测试用例
static async Task Main(string[] args){var canStop = CanStop();//等待3s抛出异常Console.WriteLine("等待3s启动");await Task.Delay(1000 * 3);Console.WriteLine("启动!");canStop.Set();Console.WriteLine("等待3s暂停");await Task.Delay(3000);Console.WriteLine("暂停!");canStop.Reset();Console.ReadKey();}public static ManualResetEvent CanStop(){var resetEvent = new ManualResetEvent(false);var count = 0;Task.Run(async () =>{while (true){resetEvent.WaitOne();await Task.Delay(1000);count++;Console.WriteLine(count);}});return resetEvent;}
多任务等最快
await Task.WhenAny(Task1,Task2,Task3)
只会等待最快的一个。
static async Task Main(string[] args){await Task.WhenAny(Sleep(1),Sleep(2),Sleep(3));Console.WriteLine("运行结束");Console.ReadKey();}public async static Task Sleep(int second){await Task.Delay(second*1000);Console.WriteLine($"等待{second}s");}
运行结果
多任务全等待
static async Task Main(string[] args){await Task.WhenAll(Sleep(1), Sleep(2), Sleep(3));Console.WriteLine("运行结束");Console.ReadKey();}public async static Task Sleep(int second){await Task.Delay(second*1000);Console.WriteLine($"等待{second}s");}
结论
异步线程的控制是极其重要的内容,Task还可以和委托一起使用,对程序的运行有更强的把控力。
相关文章:

C# Task任务详解
文章目录 前言Task返回值无参返回有参返回 async和await返回值await搭配使用Main async改造 Task进阶Task线程取消测试用例超时设置 线程暂停和继续测试用例 多任务等最快多任务全等待 结论 前言 Task是对于Thread的封装,是极其优化的设计,更加方便了我…...

百度网盘的扩容
百度网盘的扩容怎么扩 百度网盘的扩容通常需要购买额外的存储空间。以下是扩容百度网盘存储空间的一般步骤: 登录百度网盘:首先,在您的计算机或移动设备上打开百度网盘,并使用您的百度账号登录。 选择扩容选项:一旦登…...
Android 悬浮窗
本文参考文章地址:https://juejin.cn/post/7009180088310693919 一、申请权限 <uses-permission android:name"android.permission.SYSTEM_ALERT_WINDOW" />二、创建悬浮窗service <serviceandroid:name".FloatingWindowService"an…...

3.物联网射频识别,(高频)RFID应用ISO14443-2协议
一。ISO14443-2协议简介 1.ISO14443协议组成及部分缩略语 (1)14443协议组成(下面的协议简介会详细介绍) 14443-1 物理特性 14443-2 射频功率和信号接口 14443-3 初始化和防冲突 (分为Type A、Type B两种接口&…...
数据分析笔记1
数据分析概述:数据获取--探索分析与可视化--预处理--分析建模--模型评估 数据分析含义:利用统计与概率的分析方法提取有用的信息,最后进行总结与概括 一、数据获取 实用网站:kaggle 阿里云天池 数据仓库:将所有业务数据…...
paramiko 3
import paramiko import concurrent.futuresdef execute_remote_command(hostname, username, password, command):try:# 创建SSH客户端client paramiko.SSHClient()client.set_missing_host_key_policy(paramiko.AutoAddPolicy())# 使用密码认证连接远程主机client.connect(h…...
基于Dlib训练自已的人脸数据集提高人脸识别的准确率
前言 由于图像的质量、光线、角度等因素影响。这时如果使用官方提供的模型做人脸识别,就会导至识别率不是很理想。人脸识别的准确率与图像的清晰度和质量有关。如果图像模糊、光线不足或者有其他干扰因素,Dlib 可能无法正确地识别人脸。为了确保图像质量…...
Git 详细安装教程(详解 Git 安装过程的每一个步骤
Git 详细安装教程(详解 Git 安装过程的每一个步骤) 该文章详细具体,值得收藏学习...
kafka伪集群部署,使用KRAFT模式
1:拉去管理kafka界面UI镜像 docker pull provectuslabs/kafka-ui2:拉去管理kafka镜像 docker pull bitnami/kafka3:docker-compose.yml version: 3.8 services:kafka-1:container_name: kafka1image: bitnami/kafka ports:- "19092:19092"- "19093:19093&quo…...
【双指针遍历】N数之和问题
文章目录 二数之和LC1三数之和LC15四数之和LC18最接近的三数之和LC16 二数之和LC1 题目链接 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对…...
Qt的QObject类
文章目录 QObject类如何在Qt中使用QObject的信号与槽机制?如何在Qt中使用QObject的属性系统?QObject的元对象系统如何实现对象的反射功能? QObject类 Qt的QObject类是Qt框架中的基类,它是所有Qt对象的父类。QObject提供了一些常用…...

【图论C++】链式前向星(图(树)的存储)
/*** file * author jUicE_g2R(qq:3406291309)————彬(bin-必应)* 一个某双流一大学通信与信息专业大二在读 * * brief 一直在竞赛算法学习的路上* * copyright 2023.9* COPYRIGHT 原创技术笔记:转载需获得博主本人…...

16.PWM输入捕获示例程序(输入捕获模式测频率PWMI模式测频率和占空比)
目录 输入捕获相关库函数 输入捕获模式测频率 PWMI模式测频率和占空比 两个代码的接线图都一样,如下 测量信号的输入引脚是PA6,信号从PA6进来,待测的PWM信号也是STM32自己生成的,输出引脚是PA0。 需要配置电路连接图示如下&…...

pip version 更新
最近报了一个错: 解决办法: 在cmd输入“conda install pip” conda install pip 完了之后再输入: python -m pip install --upgrade pip ok....

Oracle - 多区间按权重取值逻辑
啰嗦: 其实很早就遇到过类似问题,也设想过,不过一致没实际业务需求,也就耽搁了;最近有业务提到了,和同事讨论,各有想法,所以先把逻辑整理出来,希望有更好更优的解决方案;…...
本次CTF·泰山杯网络安全的基础知识部分(二)
简记23年九月参加的泰山杯网络安全的部分基础知识的题目,随时补充 15(多选)网络安全管理工作必须坚持“谁主管、谁负责,谁运营、谁负责,谁使用、谁负责”的原则,和“属地管理”的原则 谁主管、谁负责&…...

MyBatis 映射文件(Mapper XML):配置与使用
MyBatis 映射文件(Mapper XML):配置与使用 MyBatis是一个强大的Java持久化框架,它允许您将SQL查询、插入、更新和删除等操作与Java方法进行映射。这种映射是通过MyBatis的映射文件,通常称为Mapper XML文件来实现的。本…...

基于 SpringBoot 的大学生租房网站
文章目录 1 简介2 技术栈3 需求分析4 系统设计5 系统详细设计5.1系统功能模块5.2管理员模块5.3房主功能模块5.4用户功能模块 源码咨询 1 简介 本大学生租房系统使用简洁的框架结构,专门用于用户浏览首页,房屋信息,房屋评价,公告资…...

BL808学习日志-0-概念理解
一、主核心的介绍 1.三个核心在FREERTOS系统中相互独立,各负责各自的外设和程序;其中M0和LP核心在一个总线上,D0单独在一个总线上,两个总线使用AXI4.0(??)通讯? CPU0(M0)-E907架构,320MHz; CPU1(LP)-E9…...
CISSP学习笔记:业务连续性计划
第三章 业务连续性计划 3.1 业务连续性计划 业务连续性计划(BCP): 对组织各种过程的风险评估,发生风险的情况下为了使风险对组织的影响降至最小而定制的各种计划BCP和DRP首先考虑的人不受伤害,然后再解决IT恢复和还原问题BCP的主要步骤: 项…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...

小智AI+MCP
什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析:AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github:https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...

李沐--动手学深度学习--GRU
1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...
手动给中文分词和 直接用神经网络RNN做有什么区别
手动分词和基于神经网络(如 RNN)的自动分词在原理、实现方式和效果上有显著差异,以下是核心对比: 1. 实现原理对比 对比维度手动分词(规则 / 词典驱动)神经网络 RNN 分词(数据驱动)…...

npm安装electron下载太慢,导致报错
npm安装electron下载太慢,导致报错 背景 想学习electron框架做个桌面应用,卡在了安装依赖(无语了)。。。一开始以为node版本或者npm版本太低问题,调整版本后还是报错。偶尔执行install命令后,可以开始下载…...
软件工程教学评价
王海林老师您好。 您的《软件工程》课程成功地将宏观的理论与具体的实践相结合。上半学期的理论教学中,您通过丰富的实例,将“高内聚低耦合”、SOLID原则等抽象概念解释得十分透彻,让这些理论不再是停留在纸面的名词,而是可以指导…...