普通函数

string Func()
{
string x = X();
string y = Y();
string z = Z(); return x + y + z;
}

X(), Y(), Z()内部都Sleep 10s, 则Func()耗时30s

异步函数

async string FuncAsync()
{
string x = await XAsync();
string y = await YAsync();
string z = await ZAsync(); return x + y + z;
}

假设 XAsync(), YAsync(), YAsync()内部都Sleep10s, 则FuncAync()还是耗时多少呢?

整个FuncAsync会被拆成如下部分:

  1. FuncAsync-开始部分();
  2. XAsync();
  3. FuncAsync-中间部分1();
  4. YAsync();
  5. FuncAsync-中间部分2();
  6. ZAsync();
  7. FuncAsync-结束部分();

这些部分会被.NET同步上下文SynchronizationContext在同一个线程依次执行,如下:

  1. 同步上下文执行 FuncAsync-开始部分();
  2. 同步上下文执行 XAsync(); //内部调用了Sleep10s, 要10s才返回
  3. 同步上下文执行 FuncAsync-中间部分1();
  4. 同步上下文执行 YAsync();//内部调用了Sleep10s, 要10s才返回
  5. 同步上下文执行 FuncAsync-中间部分2()
  6. 同步上下文执行 ZAsync();//内部调用了Sleep10s, 要10s才返回
  7. 同步上下文执行 FuncAsync-结束部分();

所以耗时时间还是30s

假设 XAsync(), YAsync(), YAsync()内部都把Sleep10s用Task.Run()都包起来返回

  1. 同步上下文执行 FuncAsync-开始部分();
  2. 同步上下文执行 XAsync(); 立刻返回, 在另一个线程执行Sleep(10)
  3. 同步上下文等待 但可以执行其他异步任务, 如果是Winform的话UI不会卡
  4. 后台线程10s结束告诉同步上下文继续执行
  5. 同步上下文执行 FuncAsync-中间部分1();
  6. 同步上下文执行 YAsync(); 立刻返回, 在另一个线程执行Sleep(10)
  7. 同步上下文等待 但可以执行其他异步任务, 如果是Winform的话UI不会卡
  8. 后台线程10s结束告诉同步上下文继续执行
  9. 同步上下文执行 FuncAsync-中间部分2()
  10. 同步上下文执行 ZAsync(); 立刻返回, 在另一个线程执行Sleep(10)
  11. 同步上下文等待 但可以执行其他异步任务, 如果是Winform的话UI不会卡
  12. 后台线程10s结束告诉同步上下文继续执行
  13. 同步上下文执行 FuncAsync-结束部分();

所以FuncAsync总耗时时间还是30s,优点是UI线程不会被卡住, UI线程不是被FuncAsync一个任务占有,其他异步任务也能在UI线程上执行,真正等待的任务都运行在后台线程。

下面这个版本,FuncAsync()执行的时间才是10s

async string FuncAsync()
{
var taskX = XAsync();
var taskY = YAsync();
var taskZ = ZAsync(); await Task.WhenAll(taskX, taskY, taskZ); return taskX.Result + taskY.Result + taskZ.Result;
}

如果在XAsync()里调用Task.Result同步等待会怎样?

  1. 同步上下文执行 FuncAsync-开始部分();
  2. 同步上下文执行 XAsync();    
    1.   XAsync() 调用 YAsync()  返回task             
      1.   YAsync() 开启后台线程sleep10s
    2.   XAsync()等待task.Result    
  3. 后台线程10s结束告诉同步上下文继续

XAsync要等待的结果(task.Result),需要同步上下文返回,

虽然后台线程已经同步上下文结果了,但同步上下文此时却还在执行XAsync的过程中.

互相等待,于是产生死锁.

举个形象的例子:

  1. 医生Doctor给病人Patients看病, 病人必须先排队,按次序来。
  2. 轮到某个病人PatientX时要某项检查报告,病人说,等我一下,检查报告在我老婆手里,我打电话让她送来。
  3. 于是医生Doctor和病人PatientX开始等待, 左等右等不来。
  4. 其实几分钟后病人的老婆PatientXWife已经把检查报告送来了, 只不过她拿着检查报告在队列里等。

async/await的一些用法的更多相关文章

  1. js中回调函数,promise 以及 async/await 的对比用法 对比!!!

    在编程项目中,我们常需要用到回调的做法来实现部分功能,那么在js中我们有哪些方法来实现回调的? 方法1:回调函数 首先要定义这个函数,然后才能利用回调函数来调用! login: function (f ...

  2. [.NET] 怎样使用 async & await 一步步将同步代码转换为异步编程

    怎样使用 async & await 一步步将同步代码转换为异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6079707.html  ...

  3. [.NET] 利用 async & await 进行异步 IO 操作

    利用 async & await 进行异步 IO 操作 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6082673.html  序 上次,博主 ...

  4. async/await,了解一下?

    上一篇博客我们在现实使用和面试角度讲解了Promise(原文可参考<面向面试题和实际使用谈promise>),但是Promise 的方式虽然解决了 callback hell,但是这种方式 ...

  5. promise async await使用

    1.Promise (名字含义:promise为承诺,表示其他手段无法改变) Promise 对象代表一个异步操作,其不受外界影响,有三种状态: Pending(进行中.未完成的) Resolved( ...

  6. promise 进阶 —— async / await 结合 bluebird

    一.背景 1.Node.js 异步控制 在之前写的 callback vs async.js vs promise vs async / await 里,我介绍了 ES6 的 promise 和 ES ...

  7. javascript异步编程 Async/await

    Async/await Async/await 在学习他之前应当补充一定的 promise 知识 它是一种与 promise 相配合的特殊语法,目前被认为是异步编程的终级解决方案 值得我们每一个人学习 ...

  8. async,await,Task 的一些用法

    async,await,Task 的一些用法 private void Form1_Load(object sender, EventArgs e) { Display(); } public asy ...

  9. 异步操作之 Promise 和 Async await 用法进阶

    ES6 提供的 Promise 方法和 ES7 提供的 Async/Await 语法糖都可以更好解决多层回调问题, 详细用法可参考:https://www.cnblogs.com/cckui/p/99 ...

随机推荐

  1. HTML5:了解Polyfills

    利用 HTML5 来搭建网站和应用可能是一项艰巨的任务.尽管现在越来越多的现代浏览器正在更多的支持Html5新特性,但实际上只有很少部分人能够幸运的只需要为这些最新的浏览器编写代码.作为一个专业的开发 ...

  2. [C#]ref,out关键字的作用

    ref是传递参数的地址,out是返回值,两者有一定的相同之处,不过也有不同点. 使用ref前必须对变量赋值,out不用 out的函数会清空变量,即使变量已经赋值也不行,退出函数时所有out引用的变量都 ...

  3. Prism 4 文档 ---第10章 Silverlight和WPF之间共享代码

        本主题帮助你理解来自Prism的多目标和它的优缺点.多目标的代码针对两个不同的平台有大致相同的代码库.这允许同时保持代码尽可能多一样能够产生针对两种不同技术的二进制文件.在这种情况下,本节介绍 ...

  4. LeetCode OJ:Generate Parentheses(括号生成)

    Given n pairs of parentheses, write a function to generate all combinations of well-formed parenthes ...

  5. 20165202 实验二 Java面向对象程序设计

    实验二 Java面向对象程序设计 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:贾海粟 学号:20165202 指导教师:娄嘉鹏 实验日期:2018年4月16日 实验时间:15:3 ...

  6. HAWQ取代传统数仓实践(十九)——OLAP

    一.OLAP简介 1. 概念 OLAP是英文是On-Line Analytical Processing的缩写,意为联机分析处理.此概念最早由关系数据库之父E.F.Codd于1993年提出.OLAP允 ...

  7. angular 中不要使用location.href

    location.href = '#/HKorderList?gid='+gid+'&gname='+encodeURIComponent(gname)+'&cPeriod='+$(' ...

  8. MVC MVVM和传统三层的理解

    才学疏浅,请勿喷,如果有理解不对的地方请留言 其实,每个小小的程序员都有个毛病,就是反复写一个东西会觉得这个东西没有新意. 就像让你写三层,你却还是觉得想写MVC模式. 软件小公司做B/S的大部分还是 ...

  9. Django项目部署(阿里云)(2)--扩展

    新博客地址:http://muker.net/django-server-two.html 前面的只是最简单的部署,真实情况总是更复杂一点实际流程大概是这么操作的(我这种菜鸟的想法):本地写代码-&g ...

  10. POJ3686 The Windy's 【费用流】*

    POJ3686 The Windy’s Description The Windy’s is a world famous toy factory that owns M top-class work ...