原文地址:Task 异步小技巧 - 一事冇诚 - 博客园 (cnblogs.com)

async Task 语法糖出来后,异步编程变得非常简单,适合需要耗费较长时间的任务。

有些小伙伴使用后可能会非常疑惑,使用异步和同步,在耗时上几乎没有差别。

下面我们看一个例子,场景是需要调用多个第三方的WebApi,分别是获取名称、年龄、性别,由于网络环境等原因,api响应时间可能会接近1秒

 1 public async Task Test()
2 {
3 var sw = new Stopwatch();
4 sw.Start();
5
6 var userName = await GetUserNameAsync();
7 var userAge = await GetUserAgeAsync();
8 var userSex = await GetUserSexAsync();
9
10 sw.Stop();
11 var ts = sw.Elapsed;
12 Console.WriteLine($"总共耗时:{ts.TotalMilliseconds}ms");
13 }
14
15 private async Task<string> GetUserNameAsync()
16 {
17 await Task.Delay(500);
18 return "小明";
19 }
20
21 private async Task<string> GetUserAgeAsync()
22 {
23 await Task.Delay(800);
24 return "11";
25 }
26
27 private async Task<string> GetUserSexAsync()
28 {
29 await Task.Delay(900);
30 return "11";
31 }

运行后发现,这个时间2秒多,这用户体验肯定是无法忍受的

导致这样结果的原因是每次进行异步调用的时候,都在异步函数前加上了 await ,这会导致该线程阻塞,等待直到结果返回,每个异步函数都await,时间自然就叠加了,为了解决这个问题,使用一个小技巧,可以将代码改成下面这样

 1 public async Task Test()
2 {
3 var sw = new Stopwatch();
4 sw.Start();
5
6 var userNameTask = GetUserNameAsync();
7 var userAgeTask = GetUserAgeAsync();
8 var userSexTask = GetUserSexAsync();
9
10 var userName = await userNameTask;
11 var userAge = await userAgeTask;
12 var userSex = await userSexTask;
13
14 sw.Stop();
15 var ts = sw.Elapsed;
16 Console.WriteLine($"总共耗时:{ts.TotalMilliseconds}ms");
17 }
18
19 private async Task<string> GetUserNameAsync()
20 {
21 await Task.Delay(500);
22 return "小明";
23 }
24
25 private async Task<string> GetUserAgeAsync()
26 {
27 await Task.Delay(800);
28 return "11";
29 }
30
31 private async Task<string> GetUserSexAsync()
32 {
33 await Task.Delay(900);
34 return "11";
35 }

这次运行的总耗时,就是3个异步中,耗时最长那个 GetUserSexAsync

为什么会这样呢,这个小技巧的关键是这里,当执行到异步函数的时候,不加 await,不进行等待,这样就不会造成阻塞,让这些任务乖乖在别的线程的执行,当需要用到他们的时候,再去等待返回值,所以时间上不会进行叠加,哪个最长,总耗时就是哪个

1 var userNameTask =  GetUserNameAsync();
2 var userAgeTask = GetUserAgeAsync();
3 var userSexTask = GetUserSexAsync();
4
5 var userName = await userNameTask;
6 var userAge = await userAgeTask;
7 var userSex = await userSexTask;

最新文章

  1. layoutSubviews 与 drawRect
  2. Reactor模式通俗解释
  3. ubuntu 12.04 react-native 安装
  4. mybatis 3.2.7 与 spring mvc 3.x、logback整合
  5. 玩转单元测试之WireMock -- Web服务模拟器
  6. xss实例-输出在&lt;script&gt;&lt;/script&gt;之间的情况
  7. 好用的json-path
  8. web项目设计与开发——DBHelper
  9. android 58 jvm和dvm的区别(Dalvil VM)
  10. VS代码生成工具ReSharper使用手册:配置快捷键
  11. CentOS下安装无线网卡驱动 (转)
  12. 关于MVC EntityType has no key defined的问题
  13. 12款Linux系统恢复工具
  14. Android中常用的URI
  15. Linux chmod命令及权限含义
  16. python TypeError: &#39;int&#39; object is not callable 问题解决
  17. Easyui datagrid 特殊处理,记录笔记
  18. html5-css的引入
  19. UI基础四:简单的assign block
  20. flask_admin 笔记四 自定义视图

热门文章

  1. 2020年秋游戏开发-flappy bird
  2. win系统打不开CHM文件(例如JDK的API)
  3. Kickstart部署之HTTP架构
  4. Spring系列之Mybatis动态代理实现全过程?回答正确率不到1%
  5. [考试总结]noip模拟44
  6. Python习题集(五)
  7. SpingBoot-Dubbo-Zookeeper-分布式
  8. Sonarqube C# 配置资料整理
  9. Windows安装Docker &amp; Docker-Compose &amp; 配置docker私有仓库
  10. sed 找出含有某个字符串的行 注释掉