小明用async/await写了几年的异步方法,但总没有完全理解里面的机制,他决定去请教邻居小花。

小花听了小明的描述后说:首先你要明白异步的根本是什么?大白话解释异步就是:拉一个人(线程)帮着做一些耗时的事(下载、读写数据库等),自己先做别的事了(退出线程),等做好了和我说下,我再继续做后面的事(恢复上下文)。

小花看到小明还没有听明白,就说:我举个简单例子帮你理解吧,假如有两个方法A和B,A调用B方法,B方法是一个异步方法,这时A不等待B执行完,如图:

现在两个方法被分隔几个小块,await关键字其实就用来隔开同步和异步,上面的方法执行流程如下:

A调用B方法后,B方法在未执行到await之前还是同步方法,比如输出Sub1还是在当前线程中执行,当方法遇到await后,就会把await后的方法放到新的线程中执行,当前线程则退出函数,由于调用的地方并没有await,则主线程会继续执行并输出Part2,然后结束。等新线程中Thread.Sleep(5000)执行完后,会执行到Console.Write("Sub2");这一行代码会回到原来的线程执行,其实调用线程在遇到await时会捕获当前线程的执行上下文,然后给到新线程,新线程在执行完耗时操作后,会判断之前捕获到的执行上下方是否为null,如果不为null,则会在上下文中恢复并执行后面的方法,其实就是通过Tak的ContineWith方法注册回调,如图:

小明好像听懂了一些说:现在A方法调用DoSomethingAsync()并没有等待,如果A方法需要这个方法执行完才能继续执行,是不是要在DoSomethingAsync()前面加上await?小花回答是,并说:方法只要遇到await,就会把后面的方法给新线程执行,然后退出线程去执行别的方法,等新线程执行完后再通知当前线程恢复上下文继续执行,如图:

小明又问:你说异步方法执行完后,后面的方法会在原来的线程中恢复并执行,如果我还想在新线程中继续执行剩下的代码,要怎么办呢?小花说问的好,await调用新线程执行耗时操作时默认会捕获当前上下文,如果不想捕获,则可以调用ConfigAwait(false)方法,如图:

执行流程如下:

小花补充到,上线提到的线程1、线程2、线程3等不一定准确,因为异步的回调使用的是线程池中的线程,所以回调有可能还在原来线程中执行,这个主要看操作系统的调度。

小明满意地点点头又问:我经常听同事说用异步方法会死锁,这又是为什么呢?小花听了说,他们肯定是在调用异步方法的时候使用.Result(),如图:

小花指着图解释说:上面的代码task.Result()会阻塞线程并等待task返回结果,DoSomethingAsync方法在执行完Thread.Sleep(5000)后,发现捕获到的上下文不为空,则会尝试将Console.Write("Sub2")这行代码交由调用线程去执行,而这时调用线程还在阻塞等待,就这样互相卡着对方,从而造成了死锁,如图:

小明点了点头又问:那要怎么避免呢?小花说出现这种情况也和框架有关,像WinForm为了让所有UI操作都在主线程中执行,就添加了一个SynchronizationContext类实例用以表示当前上下文,而像控制台等项目这个SynchronizationContext实例默认为null,所以即使使用.Result也不会死锁。但最好使用异步的时候不要用.Result,可以使用ConfigAwait(false)指明不捕获上下文,或所有的方法全部异步到底。

小明听完,拜别了小花,回到了自己的隔间。

简单说说async/await相关推荐

  1. 玩转异步 JS :async/await 简明教程(附视频下载)

    课程介绍 在软件开发领域,简洁的代码 => 容易阅读的代码 => 容易维护的代码,而 ES2017 中的 async/await 特性能让我们编写出相比回调地狱和 Promise 链式调用 ...

  2. 【转】C# 彻底搞懂async/await

    关键: 异步方法:在执行完成前立即返回调用方法,在调用方法继续执行的过程中完成任务. async/await 结构可分成三部分: (1)调用方法:该方法调用异步方法,然后在异步方法执行其任务的时候继续 ...

  3. promise 和 async await区别

     什么是Async/Await? async/await是写异步代码的新方式,以前的方法有回调函数和Promise. async/await是基于Promise实现的,它不能用于普通的回调函数. as ...

  4. async await:比requests 更强大

    最近公司 Python 后端项目进行重构,整个后端逻辑基本都变更为采用"异步"协程的方式实现.看着满屏幕经过 async await(协程在 Python 中的实现)修饰的代码,我 ...

  5. @async 默认线程池_.NET Web应用中为什么要使用async/await异步编程?

    布莱恩特:.NET Core开发精选文章目录,持续更新,欢迎投稿!​zhuanlan.zhihu.com 前言 1.什么是async/await? await和async是.NET Framework ...

  6. 8张图让你一步步看清 async/await 和 promise 的执行顺序

    2019独角兽企业重金招聘Python工程师标准>>> **摘要:**面试必问 原文:8张图帮你一步步看清 async/await 和 promise 的执行顺序 作者:ziwei3 ...

  7. 用 async/await 来处理异步

    引用出处:https://www.cnblogs.com/SamWeb/p/8417940.html 昨天看了一篇vue的教程,作者用async/ await来发送异步请求,从服务端获取数据,代码很简 ...

  8. 从不用 try-catch 实现的 async/await 语法说错误处理

    前不久看到 Dima Grossman 写的 How to write async await without try-catch blocks in Javascript.看到标题的时候,我感到非常 ...

  9. 明明有了 promise ,为啥还需要 async await ?

    作者 | Angus安格斯 来源 | https://juejin.cn/post/6960855679208783903 为了让还没听说过这个特性的小伙伴们有一个大致了解,以下是一些关于该特性的简要 ...

最新文章

  1. Python调整图片大小并保存调整后的图像
  2. Eclipse的设置、调优、使用(解决启动卡顿等问题)----转
  3. 考考大家的数学,计算以下计算公式的结果
  4. asp.net 2.0 技巧2
  5. 辍学程序员改变世界,这位长得像马云的90后要击败Facebook的扎克伯格了…
  6. 论文浅尝 | GraphSAINT—基于图采样的归纳学习方法
  7. UVa 1586 Molar mass 分子量 题解
  8. ezcad旋转轴标刻参数_激光打标机软件ezcad系统参数设置
  9. java ITEXT实现PDF生成二维码和条形码
  10. java游戏服务器开发需要学习的技术
  11. 视频资源网站采集-视频资源API采集教程
  12. 能用CSS实现的就不用麻烦JavaScript(Part2)
  13. 抖音小店无货源,怎么操作可以出单?资深电商人在线分享
  14. android修改短信内容,Android手机
  15. 让企业订单交期满足率提升3.5倍,新一代APS(高级生产计划与排程系统)是什么样的?
  16. matlab仿真环境运行,ADMIRE 飞行仿真模型,Matlab环境中运行,可实现快速 ,性能分析 274万源代码下载- www.pudn.com...
  17. Hive 产生大量的临时文件(转载)
  18. WindowsServer2019下Php(php-7.4.3-Win32-vc15-x64) 调用C# .dll文件
  19. 靠创业挣钱是最苦的路
  20. 【HDLBits 刷题 12】Circuits(8)Finite State Manchines 27-34

热门文章

  1. Delphi全局热键的注册
  2. C# 使用int.TryParse,Convert.ToInt32,(int)将浮点类型转换整数时的区别
  3. jquery this 与javascript的this
  4. 如何在PowerPoint中自动调整图片大小
  5. 酷安应用市场php源码,酷安应用市场 v11.0.3-999 去广告极限精简版
  6. C++ float的内存布局
  7. 使用CDN引用jQuery
  8. struts2配置中Action的name 和package的name和namespace作用
  9. 配置静态路由下一跳为本地出战接口和IP地址的区别
  10. cocoaChina中整理的知识点-对文件重新命名-利于查阅