异步async与await的简单探究
在学习.net core的过程中,到处见到异步的使用,Task、async、await随处可见。有点疑惑,就去了解了下这个过程是怎样的。
下面是一段代码,去看看是怎么执行的吧。
一、看看异步执行的方式
static void Main(string[] args)
{ Console.WriteLine("我是主线程:我的ID是:" + Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(); TestAsync(); Console.WriteLine("不等异步完成我先执行了哈,我的ID是:" + Thread.CurrentThread.ManagedThreadId);
Console.ReadKey(); }
/// <summary>
/// 异步方法
/// </summary>
/// <returns></returns>
static async Task TestAsync()
{
Console.WriteLine("我是TestAsync,调用我的线程ID是:" + Thread.CurrentThread.ManagedThreadId);
await Task.Run(() => {
Console.WriteLine("我是在TestAsync中开启的线程,ID是:" + Thread.CurrentThread.ManagedThreadId);
});
Console.WriteLine("TestAsync开启的线程执行完后,此时的线程ID为:" + Thread.CurrentThread.ManagedThreadId);
}

我们看到,主线程ID是1,然后调用TestAsync方法,注意在Main方法中,调用TestAsync我们没有使用await,因为在Main方法中不支持async。
主线程调用TestAsync方法,进到TestAsync之后,打印出调用TestAsync方法的线程的ID。然后遇到Task.Run开启新的线程,ID为3。Task.Run之前有await,
注意:await会阻塞当前线程,就是ID为3的线程,并且释放调用TestAsync方法的线程,也即是主线程(ID为1),这个时候我们看到"不等异步完成我先执行了哈,我的ID是:1"
输出在"TestAsync开启的线程执行完后,此时的线程ID为:4"之前。这就说明了,TestAsync方法中await释放了主线程,同时Task.Run开启了一个新的线程。
Task.Run开启的线程是从线程池中取出的空闲线程。我运行几次,发现最后一个输出的结果不一样。如下图:
这应该说明,Task.Run开启线程后,await后的代码,是会重新开启一个线程去执行的。
二、看看await是怎么阻塞之后的代码的。
static void Main(string[] args)
{ Console.WriteLine("我是主线程:我的ID是:" + Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(); TestAsync(); Console.WriteLine("不等异步完成我先执行了哈,我的ID是:" + Thread.CurrentThread.ManagedThreadId);
Console.ReadKey(); }
/// <summary>
/// 异步方法
/// </summary>
/// <returns></returns>
static async Task TestAsync()
{
Console.WriteLine("我是TestAsync,调用我的线程ID是:" + Thread.CurrentThread.ManagedThreadId);
await TestAsync2();
Console.WriteLine("我被阻塞了,在TestAsync2执行之后才会执行,现在的线程ID是:" + Thread.CurrentThread.ManagedThreadId);
await Task.Run(() => {
Console.WriteLine("我是在TestAsync中开启的线程,ID是:" + Thread.CurrentThread.ManagedThreadId);
});
Console.WriteLine("TestAsync开启的线程执行完后,此时的线程ID为:" + Thread.CurrentThread.ManagedThreadId);
}
static async Task TestAsync2()
{
Console.WriteLine();
Console.WriteLine("我是TestAsync2,调用我的线程ID是:" + Thread.CurrentThread.ManagedThreadId);
await Task.Run(() => {
Console.WriteLine("我是在TestAsync2中开启的线程,ID是:" + Thread.CurrentThread.ManagedThreadId);
int num = ;
for (int i = ; i < ; i++)
{
num += ;
}
Console.WriteLine($"在TestAsync2中执行一个耗点儿时间的操作,num的值是{num}");
});
}

我们看到在TestAsync中调用TestAsync2前面加了await,"我被阻塞了,在TestAsync2执行之后才会执行,现在的线程ID是:3"
在TestAsync2方法执行之后,才输出。并且这个时候主线程被释放掉了,去输出"不等异步完成我先执行了哈,我的ID是:1"。
好了,暂时就理解了这么多,肯定有不对的地方,欢迎大家指正,时间不早了,早点休息,做个佛系养生的程序员,
异步async与await的简单探究的更多相关文章
- C# 异步编程,async与await的简单学习
前提声明:C# 5.0 .NET Framework 4.5 2012-08-15 异步和等待(async和await).调用方信息(Caller Information) (C#版本与.NET版本 ...
- 异步async、await和Future的使用技巧
由于前面的HTTP请求用到了异步操作,不少小伙伴都被这个问题折了下腰,今天总结分享下实战成果.Dart是一个单线程的语言,遇到有延迟的运算(比如IO操作.延时执行)时,线程中按顺序执行的运算就会阻塞, ...
- flutter 异步async、await和Future的使用技巧
由于前面的HTTP请求用到了异步操作,不少小伙伴都被这个问题折了下腰,今天总结分享下实战成果.Dart是一个单线程的语言,遇到有延迟的运算(比如IO操作.延时执行)时,线程中按顺序执行的运算就会阻塞, ...
- .Net 4.5 的async 和await 的简单理解使用
原文地址:http://www.cnblogs.com/HJL-Blog/p/4432632.html 所谓的异步编程是利用CPU空闲时间和多核的特性,它所返回的Task或Task<TResul ...
- 异步async/await简单应用与探究
感谢Marco CAO指出的两点错误,已做出修改与补充 异步函数(async/await)简单应用 .NET Framework4.5提供了针对异步函数语法糖,简化了编写异步函数的复杂度. 下面通过一 ...
- 【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单
一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两 ...
- 转:[你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单
本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单 async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...
- [你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单
本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单 async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...
- 四、C# 5.0 新特性——Async和Await使异步编程更简单
一.引言 .NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就 ...
随机推荐
- servlet的运行机制,转发和重定向
一.当发送一个请求到服务器端的时候,容器(tomcat)会判断该路径属于哪一个servlet进行处理,servlet有一个抽象父类“httpservlet”,这个类是一个模板设计模式的类,其中serv ...
- C 语言能不能在头文件定义全局变量?
可以,但一般不会将全局变量的定义写在头文件中. 因为如果多个 C 源文件都添加了头文件,很容易引起重定义的问题.这时候一般编译器都会提示:“multiple definition of... firs ...
- Linux命令:popd
语法 popd [-n] [+N | -N | dir] 把目录弹栈,就是从栈里删除.popd只有删除一种意思,不像pushd,既有压栈,又有移动栈内目录的功能. 不带任何参数,模式删除栈顶,即最上面 ...
- AWS 实战
AWS (Amazon Web Service) 要使用亚马逊的免费云服务 AWS,必须先注册账号,然后绑定信用卡. 创建 AMI(Amazon Machine Image) 选择 EC2 服务 EC ...
- 虚拟机中安装完Lunix系统后,开机黑屏,只显示一个-,解决方法
1,查看设置->硬盘是不是SCSI,如果是,先关闭虚拟机,移除该硬盘(实际数据不会删除) 2,添加一个新的虚拟硬盘,最后位置选IDE设备 3,确定,重启虚拟机即可
- Codeforces Round #442 (Div. 2) E Danil and a Part-time Job (dfs序加上一个线段树区间修改查询)
题意: 给出一个具有N个点的树,现在给出两种操作: 1.get x,表示询问以x作为根的子树中,1的个数. 2.pow x,表示将以x作为根的子树全部翻转(0变1,1变0). 思路:dfs序加上一个线 ...
- CentOS7搭建Zookeeper环境
Linux下安装JDK 1.检查一下系统中的jdk版本 [root@localhost software]# java -version 显示: openjdk version "1.8.0 ...
- ofstream文件输出流把二进制数据写入文件
#include <fstream> #include <sstream> using namespace std; //在实际应用中,根据需要的不同,选择不同的类来定义:如果 ...
- java表达式中运算符优先级
运算符优先级:运算符*和/(以及%)的优先级高于+和-(优先级越高,越早运算) 在逻辑运算符中,!拥有最高优先级,之后是&&,接下来是||. 一般来说,相同优先级的运算符的运算顺序是从 ...
- Dubbo 的配置主要分为三大类
服务发现.服务治理和性能调优:这三类配置不是独立存在的,而是贯穿在所有配置项中的,比如dubbo:service 标签中的interface 是服务发现类, timeout是性能调优类, mock 是 ...