async/await Task.Delay 和Thread.Sleep的理解
async/await Task.Delay 和Thread.Sleep的理解
相关学习资料:
第十七节:从状态机的角度async和await的实现原理(新) - Yaopengfei - 博客园 (cnblogs.com)
C# async await 原理:编译器如何将异步函数转换成状态机 | 码农网 (codercto.com)
await——调用的等待期间,.NET会把当前的线程返回给线程池,等异步方法调用执行完毕后,框架会从线程池再取出来一个线程执行后续的代码,当前线程不会阻塞
从原理层面刨析
async与await是
语法糖,最终译成“状态机调用”。其他常用的语法糖var、using、lambda表达式等。async关键字标记的方法会被C#编译器编译成一个状态机。
await是关键字是为了实现状态机中的一个状态。
会根据方法内的await调用切分成多个状态,每当有一个await,就会生成一个对应的状态。
状态机实现了AsyncStateMachine接口,里面有MoveNext 和 SetStateMachine方法处理相应业务.

MoveNext——定义各个状态之间转换的方法
- 在await执行时调用一次,在await操作结束时继续调用
从实践方向刨析
async会将方法的返回结果包装成Task,所以它不是必需的
//使用async,实际是将Result包装成Task<Result>
//此处就是对结果通过await拆包,再通过async包装成Task<Result>返回,当前场景下没有必要,可直接简写成下面的场景
public static async Task AsyncNoReturn()
{
await Task.Delay(500);
}
//不使用async的写法,因为类型已经是Task了不需要通过async关键字包装
public static Task AsyncNoReturn1()
{
return Task.Delay(500);
}
总结:如果一个异步方法只是对别的异步方法调用的转发,并没有太多复杂的逻辑(比如等待的结果,再调用B:把调用的返回值拿到内部做一些处理再返回),那么就可以去掉async关键字。返回值为Task的方法不一定都要标注async,标注async只是让我们可以更方便的await而已
- 避免对返回结果Task的“拆包后再次包装”
- 避免在底层创建状态机,性能更优
正面Demo:
public static Task<string> DownloadFromFile(int num)
{
if (num == 1)
{
return File.ReadAllTextAsync(@"D:\1.txt");
}
else if (num == 2)
{
return File.ReadAllTextAsync(@"D:\2.txt");
}
else
{
throw new ArgumentException("Invalid Number");
}
}
如果没有在声明Task的时候前面没有加await,则主线程不会异步等待Task完成,主线程会继续往下执行,与Task并发执行
Thread.Sleep() ——会让当前线程休眠,形成阻塞,当前休眠结束后继续往下执行
await Task.Delay()——当前线程返回线程池,从线程池拿另外一个空闲线程线程做定时任务,等待任务结束后,从线程池拿到一个空闲线程,继续往下执行。
await Task.Delay(200);
//可理解等效成如下代码
await Task.Run(() =>
{
Thread.Sleep(200);
});
区别:
Thread.Sleep会阻塞当前线程,但是从线程池另取线程;Task.Delay不会阻塞当前线程,但是会新取一个线程
Thread.Sleep不可取消,Task.Delay可取消
public static Task Test_Delay()
{
//创建一个5秒的异步等待
Task delay1 = Task.Delay(TimeSpan.FromSeconds(5));
return delay1;
}
在Main方法里测试
static void Main(string[] args)
{
//Task在声明处就开始执行
var test = Test_Delay();
//主线程等待2秒钟
Thread.Sleep(TimeSpan.FromSeconds(2));
Stopwatch sw = new Stopwatch();
sw.Start();
//当前线程等待test指向的Task执行结束
test.Wait();
sw.Stop();
TimeSpan ts = sw.Elapsed;
Console.WriteLine($"Task.Delay执行结束,耗时:{ts.TotalMilliseconds}");
Console.ReadKey();
}
结果打印:
Task.Delay执行结束,耗时:3004.527
上面显示大概监听为3秒。这个表示了当前主线程在运行的时候,Task.Delay也在运行,这个只有在不同线程才可以实现。
async/await Task.Delay 和Thread.Sleep的理解的更多相关文章
- async/await Task Timeout
async/await Task Timeout 在日常的电脑使用过程中,估计最难以忍受的就是软件界面"卡住""无响应",在我有限的开发生涯中一直都是在挑战 它 ...
- Task C# 多线程和异步模型 TPL模型 【C#】43. TPL基础——Task初步 22 C# 第十八章 TPL 并行编程 TPL 和传统 .NET 异步编程一 Task.Delay() 和 Thread.Sleep() 区别
Task C# 多线程和异步模型 TPL模型 Task,异步,多线程简单总结 1,如何把一个异步封装为Task异步 Task.Factory.FromAsync 对老的一些异步模型封装为Task ...
- async await Task
一.使用Task 引用命名空间 using System.Threading.Tasks; 1.工厂方式 Task.Factory.StartNew(() => {Console.WriteLi ...
- async,await,Task 的一些用法
async,await,Task 的一些用法 private void Form1_Load(object sender, EventArgs e) { Display(); } public asy ...
- C#扫盲篇(四):.NET Core 的异步编程-只讲干货(async,await,Task)
关于async,await,task的用法和解释这里就不要说明了,网上一查一大堆.至于为啥还要写这篇文章,主要是其他文章水分太多,不适合新手学习和理解.以下内容纯属个人理解,如果有误,请高手指正.本文 ...
- c#5.0(.net 4.5之后)的 Async+await+Task的异步机制的调试笔记
1.)无返回值的情况(异步也是基于线程). using System; using System.Collections.Generic; using System.Linq; using Syste ...
- Task.Delay() 和 Thread.Sleep() 区别
1.Thread.Sleep 是同步延迟,Task.Delay异步延迟. 2.Thread.Sleep 会阻塞线程,Task.Delay不会. 3.Thread.Sleep不能取消,Task.Dela ...
- task.delay 和 thread.sleep
1.Thread.Sleep 是同步延迟. Task.Delay异步延迟. 2.Thread.Sleep 会阻塞线程,Task.Delay不会. 3.Thread.Sleep不能取消,Task.Del ...
- async await Task 使用方法
使用概述 C#的使用过程中,除了以前的Thread.ThreadPool等用来开一个线程用来处理异步的内容.还可以使用新特性来处理异步.比以前的Thread和AutoResetEvent.delege ...
- async await task.Result 卡死
在如下代码中: public async Task<string> GetData() { return await DoWork(); } 在UI线程中调用 var data = Get ...
随机推荐
- 彰显科技硬实力!天翼云论文在国际顶刊JoCCASA发表!
近日,由天翼云科技有限公司云网产品事业部混合云团队完成的论文<Multivariate Time Series Collaborative Compression for Monitoring ...
- 解决“yarn : 无法加载文件 C:\Users\quber\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本”问题
1.问题描述 我们在使用yarn命令的时候,可能会出现如下图所示的错误: 2.解决办法 出现此错误的原因是本地计算机上运行你编写的未签名脚本和来自其他用户的签名脚本,可以使用如下命令将计算机上的执行策 ...
- 如何让领导轻松在本地查看Allure报告
如何让领导轻松在本地查看Allure报告 问题描述 当我们把精心生成的Allure报告原始文件发送给领导后,领导直接打开index.html文件时,页面却一直处于加载状态,无法显示数据. 通过F12开 ...
- Linux查看和操作文件内容命令
Linux查看和操作文件内容命令 文件查看命令 在Linux中,有多种命令可以帮助我们查看文件的内容.以下是其中一些常用的命令及其简要说明: cat命令 cat 命令用于显示文件的内容,特别适用于查看 ...
- 同步工具-Oceanus打通mysql到Iceberg
一.服务配置 已配置好gt_oneline_2,其它集群还需按照下面方式特殊配置 1.需要腾讯Oceanus同学在后端修改高途flink集群配置core-site.xml文件,增加如下配置.只能绑定一 ...
- Java连接数据库 CreateStatement 和 PrepareStatement 的区别与优劣
一.简介 先说下CreateStatement 和 PrepareStatement 这俩到底是干啥的吧. 作用:其实这俩干的活儿都一样,就是创建了一个对象然后去通过对象调用executeQuery方 ...
- PADS无模命令总结表
无模命令总结表 1.C 补充格式,在内层负片设计时用来显示 Plane 层的焊盘及 Thermal.使用方法是,从键盘上输入 C 显示,再次输入 C 可去除显示. 2.D 打开/关闭当前层显示,使用方 ...
- 【COM3D2Mod 制作教程(6)】实战!制作身体部分(下)
[COM3D2Mod 制作教程(6)]实战!制作身体部分(下) 有了上一章制作帽子的经验,此时做头发很多就不必再重复赘述了,但如果用完全一样的流程和方法,把头发做好后直接装扮就会导致游戏报错,这就是我 ...
- Eclipse各历史版本所需的最低JDK版本统计
Eclipse 版本名称 Version 发布时间 最低支持的jdk Kepler 4.3 2013.06 Java 6 Luna 4.4 2014.06.25 Java 7 Mars 4.5 201 ...
- MySQL时间溢出原理、实战影响与全面解决方案
一.问题背景与现象复现 操作场景: 本文将手把手带您了解mysql时间溢出原理.实战影响与全面解决方案,所有代码均通过dblens for mysql数据库工具验证,推荐使用该工具进行可视化数据库管理 ...