在学习.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的简单探究的更多相关文章

  1. C# 异步编程,async与await的简单学习

    前提声明:C# 5.0 .NET Framework 4.5 2012-08-15 异步和等待(async和await).调用方信息(Caller Information)  (C#版本与.NET版本 ...

  2. 异步async、await和Future的使用技巧

    由于前面的HTTP请求用到了异步操作,不少小伙伴都被这个问题折了下腰,今天总结分享下实战成果.Dart是一个单线程的语言,遇到有延迟的运算(比如IO操作.延时执行)时,线程中按顺序执行的运算就会阻塞, ...

  3. flutter 异步async、await和Future的使用技巧

    由于前面的HTTP请求用到了异步操作,不少小伙伴都被这个问题折了下腰,今天总结分享下实战成果.Dart是一个单线程的语言,遇到有延迟的运算(比如IO操作.延时执行)时,线程中按顺序执行的运算就会阻塞, ...

  4. .Net 4.5 的async 和await 的简单理解使用

    原文地址:http://www.cnblogs.com/HJL-Blog/p/4432632.html 所谓的异步编程是利用CPU空闲时间和多核的特性,它所返回的Task或Task<TResul ...

  5. 异步async/await简单应用与探究

    感谢Marco CAO指出的两点错误,已做出修改与补充 异步函数(async/await)简单应用 .NET Framework4.5提供了针对异步函数语法糖,简化了编写异步函数的复杂度. 下面通过一 ...

  6. 【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单

    一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两 ...

  7. 转:[你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单

    本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单  async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...

  8. [你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单

    本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单  async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...

  9. 四、C# 5.0 新特性——Async和Await使异步编程更简单

    一.引言 .NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就 ...

随机推荐

  1. python读取excel,返回dic列表

    def get_xls_sheets_as_dic(pro_name, xls_name): dic_list = [] xls_path = os.path.join(BASE_PATH, &quo ...

  2. springboot 开启事务以及手动提交事务

    添加依赖,sprongboot 会默认开启事务管理 org.springframework.boot spring-boot-starter-jdbc 在需要的服务类里添加注解 @Autowired ...

  3. JAVA设计方法思考之如何实现一个方法执行完毕后自动执行下一个方法

    今天编程时,突然想起来在一些异步操作或Android原生库的时候,需要我们实现一些方法, 这些方法只需要我们具体实现,然后他们会在适当的时候,自动被调用! 例如AsyncTask,执行玩doInBac ...

  4. 【译】在Transformer中加入相对位置信息

    目录 引言 动机 解决方案 概览 注释 实现 高效实现 结果 结论 参考文献 本文翻译自How Self-Attention with Relative Position Representation ...

  5. linux 之 shell

    echo 输出命令 语法:echo [选项][输出内容] 选项 -e:支持反斜线控制的字符转换 范例 vi hello.sh #!/bin/bash #author liuch echo " ...

  6. maven+springMVC+mybatis+sqlserver数据

    因为之前搭好的是maven+springMVC+mybatis+mysql数据库环境,但是在实际工作项目是使用的sqlserver数据库,本文是针对数据库从mysql切换到sqlserver数据库 s ...

  7. Spring Boot与Docker部署

    开启Docker远程访问 首先需要开启docker远程访问功能,以便可以进行远程操作. CentOS 6 修改/etc/default/docker文件,重启后生效(service docker re ...

  8. 爬虫之Splash

    Splash 是一个JavaScript渲染服务,是一个带有HTTP API 的轻量级浏览器,同时它对接了Python中Twisted和QT库. 1.功能介绍 1)异步方法处理多个网页渲染过程: 2) ...

  9. word里如何将模板的样式(标题啊、字体啊)导入到另外的模板里

    点进去

  10. SpringCloud-day07-Feign

    7.Feign 7.1.Feign简介 声明式服务调用Feign简单介绍下: Feign是一个声明式的Web Service客户端,它使得编写Web Serivce客户端变得更加简单.我们只需要使用F ...