先假设如下场景:

主函数 Main,循环等待用户输入;

计算函数 Cal,耗时计算大量数据;

class Test
{static int Main(string[] args){while(true){// 等待用户输入}}public static int Cal() {int sum = 0;for (int i = 0; i < 999; i++){sum = sum + i;}Console.WriteLine($"sum={sum}");return sum;}
}

为了在Main函数中调用Cal函数,同时Cal函数不阻塞主函数的循环,此时需要考虑增加一个CalAsync函数使Cal函数异步执行。

传统的思维方法  在CalAsync函数中启动一个线程,并在线程中执行Cal函数:

// using System.Threading;
public static CalAsync()
{Thread td = new Thread(new ThreadStart(Cal));td.start();
}

这种方法显示地创建了一个线程并启动执行,CalAsync函数本身还是在主线程执行并且无法直接获取Cal函数的结果。

async 和 await 异步编程方法  使用async标记CalAsync函数,并在CalAsync函数中创建任务Task异步执行Cal函数,同时使用await标记获取Cal函数的执行结果:

// using System.Threading.Tasks;
public static aysnc void CalAsync()
{int result = await Task.Run(new Func<int>(Cal));// 或使用lambda书写方式//  int result = await Task.Run(() => test());Console.WriteLine(result);
}

在Main函数中直接调用CalAsync函数,可以发现CalAsync成功调用了Cal函数并在一段时间后输出了结果,同时Main函数并不会被阻塞。

分别在Main、Cal、CalAsync函数中增加代码打印当前线程ID:

class Test
{static void Main(string[] args){string tid = Thread.CurrentThread.ManagedThreadId.ToString();Console.WriteLine($"Main1 tid {tid}");Task<int> t = CalAsync();Console.WriteLine($"Main after CalAsync");Console.Read();}public static int Cal(){string tid = Thread.CurrentThread.ManagedThreadId.ToString();Console.WriteLine($"Cal tid {tid}");int sum = 0;for (int i = 0; i < 999; i++){sum = sum + i;}Console.WriteLine($"sum={sum}");return sum;}public static async Task<int> CalAsync(){string tid = Thread.CurrentThread.ManagedThreadId.ToString();Console.WriteLine($"CalAsync1 tid {tid}");int result = await Task.Run(new Func<int>(Cal));tid = Thread.CurrentThread.ManagedThreadId.ToString();Console.WriteLine($"CalAsync2 tid {tid}, result={result}");return result;}
}

结果如图:

可以看出,在CalAsync函数中,await标记之前,代码在主线程中执行,而await标记之后,代码在子线程中执行。

理解与结论:

  • 在C#中, async标记了一个包含异步执行的函数,通过async标记的函数若在主线程中直接调用,则函数一开始仍在主线程中执行;

  • aysnc标记的函数内部必须包含await标记需要异步执行的函数(根据vs2017编译提示),若当前函数在主线程中直接调用,则await标记前的代码在主线程中执行,await标记后的代码在其异步子线程中执行;

  • async标记的函数返回值必须为void、Task、Task< TResult> 类型,可以理解为async标记的函数返回的是 “空”、“即将执行的任务”、“带结果的即将执行的任务”实例;

  • async标记的函数可以继续往下调用async标记函数,调用形式如下例, 从调用逻辑可以理解为await实际上用来触发所标记的Task任务异步执行,并最后获取异步执行的返回值,从运行过程看该触发应该仅对最终的Task任务有效:

 public static async Task<int> CallCalAsync(){string tid = Thread.CurrentThread.ManagedThreadId.ToString();Console.WriteLine($"CallCalAsync1 tid {tid}");int result = await CalAsync();tid = Thread.CurrentThread.ManagedThreadId.ToString();Console.WriteLine($"CallCalAsync2 tid {tid}, result={result}");return result;}

总结

C#中async与await异步编程,可以理解为:

1. async声明了一个包含异步执行代码的函数,该函数执行时不会阻塞调用线程;

2. await存在于async函数中,声明了一个异步执行入口,程序动态运行时从该入口创建并进入一个异步线程环境,并在该线程执行任务实例及任务实例返回之后的代码;

3. 一个async函数中声明多个await关键字时,程序将代码顺序创建并进入异步子线程执行任务实例及任务实例返回之后的代码直到下一个await声明处, 最后一个await声明之后的代码会在最后一个异步子线程中执行 ;

3. await标记的右侧代码返回或定义了一个任务实例,该实例由需要异步执行的目标耗时函数初始化,并在最终定义处触发异步执行。

C# async 和 await 理解相关推荐

  1. async和await理解代码

    <1>:Async和Await的理解1 using System; using System.Collections.Generic; using System.Linq; using S ...

  2. 第十五节:深入理解async和await的作用及各种适用场景和用法

    一. 同步VS异步 1.   同步 VS 异步 VS 多线程 同步方法:调用时需要等待返回结果,才可以继续往下执行业务 异步方法:调用时无须等待返回结果,可以继续往下执行业务 开启新线程:在主线程之外 ...

  3. JavaScript 的 async/await 理解(4)

    随着 Node 7 的发布,越来越多的人开始研究据说是异步编程终级解决方案的 async/await.我第一次看到这组关键字并不是在 JavaScript 语言里,而是在 c# 5.0 的语法中.C# ...

  4. 理解async与await

    1. async和await是什么 async可以理解为generate的语法糖,async是异步的意思,用来声明一个函数是异步的. await是等待的意思,顾名思义,它是用来等待某个动作的完成. 注 ...

  5. 小程序高级电商前端第2周深入理解REST API开发规范 开启三端分离编程之旅<二>----scroll-view组件的灵活应用、async和await问题探讨、spu-scroll自定义组件

    前言: 转眼距离上一次写博文又过去一个月了,今年的博文节奏已经彻底被打破了: 真的是有心无力了,其原因在之前也提到过,组织架构调整,各种考核(跨领域性质的考核)实行末尾淘汰制,说不出的酸楚,不过换个心 ...

  6. 理解异步函数async和await的用法

    定义 async作为一个关键字放在函数前面,表示该函数是一个异步函数,异步函数意味着该函数的执行不会阻塞后面代码的执行:而 await 用于等待一个异步方法执行完成: async/await的作用就是 ...

  7. 对于js的async和await的理解分析

    一.async和await async和await的概念 1)async 函数是 Generator 函数的语法糖,使用 关键字 async 来表示,在函数内部使用 await 来表示异步 2)ES7 ...

  8. java有async和await吗,理解 JavaScript 的 async/await

    2020-06-04 更新 JavaScript 中的 async/await 是 AsyncFunction 特性 中的关键字.目前为止,除了 IE 之外,常用浏览器和 Node (v7.6+) 都 ...

  9. javascript之异步操作理解---回调函数,async,await以及promise对象

    javascript之异步操作理解---回调函数,async,await以及promise对象 概述 概述 写在前面:虽然平时做项目,但是发现自己写的代码还是很烂.最近接触了一个对性能要求比较高的项目 ...

最新文章

  1. 我是如何利用“王宝强离婚”事件来吸粉的
  2. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 路由koa-router
  3. InfluxDB:cannot use field in group by clause
  4. ssh连接虚拟机中mysql_用SSH连接Vmware redhat虚拟机
  5. 【STM32】FreeRTOS 时间管理
  6. 区块链BaaS云服务(17)纸贵科技Z-BaaS“合约中心”
  7. Spring Cloud 微服务架构全链路实践
  8. angular ng-zorro 用组件自身方的法来重置表单校验
  9. 4.数据库的连接(编目)-远程连接
  10. python藏头诗_Python简单实现表白藏头诗-Go语言中文社区
  11. 2021-2027全球与中国Al2O3氧化铝陶瓷基板白板市场现状及未来发展趋势
  12. win系统excel、txt文件传到linux,行列数对不齐,乱码的的问题
  13. 小程序 function(res)与(res) =的区别
  14. 2021网易云任务全自动每日打卡300首搭建教程
  15. 最新版WinRAR5.61去广告代码教程分享(仅供学习交流)
  16. Win10 下安装Ubuntu 16.04双系统详解
  17. CATTI 三级笔译考试准备
  18. 技术团队负责人应该具备怎样的能力
  19. hive中的事物操作
  20. docker发布一个springboot项目真香

热门文章

  1. 【Immutable】拷贝与JSON.parse(JSON.stringify()),深度比较相等与underscore.isEqual(),性能比较...
  2. 千位分隔符的完整攻略
  3. Android 开发笔记___drawable
  4. SQL PROMPT5.3.4.1的一些设置选项
  5. 泛泰A860(高通公司8064 cpu 1080p) 拂4.4中国民营recovery TWRP2.7.1.2文本(通过刷第三版)...
  6. 网络数据库的复制和同步(转摘)
  7. vue vue的table表格自适应_响应式表格,HTML表格自适应(responsive table)
  8. linux 文件按时间 函数,[Linux文件属性]使用utime函数操作文件的时间参数
  9. 跨域问题及CORS机制
  10. Tecplot如何导入多个DAT文件后激活solution time按钮