aync await 进一步探索

首先来个例子

  1. class Program
  2. {
  3. static int index = 1;
  4. static void Log(string str)
  5. {
  6. Console.WriteLine((index++) + ". " + str + ". ThreadId:" + Thread.CurrentThread.ManagedThreadId);
  7. }
  8. static void Main(string[] args)
  9. {
  10. //解决.net core控制台输出中文乱码的代码
  11. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  12. //async 不能用于Main方法,所以在这里单独使用一个方法来调用,各位可以试试,编译不过,但VS就是不会告诉你错误在哪里
  13. ExcuteAsync();
  14. Console.ReadLine();
  15. }
  16. static async void ExcuteAsync() {
  17. Log("异步方法调用前");
  18. var ret = AsyncMethod();
  19. Log("异步方法调用后");
  20. Log(await ret);
  21. Log("异步方法使用await后");
  22. }
  23. static async Task<string> AsyncMethod() {
  24. Log("异步方法开始");
  25. var task = Task.Run<string>(() =>
  26. {
  27. Log("异步方法内部开始");
  28. Thread.Sleep(3000);
  29. Log("异步方法内部结束");
  30. return "来自异步方法内部的结果";
  31. });
  32. Log("异步方法结束");
  33. var ret = await task;
  34. Log("异步方法await结束");
  35. return ret;
  36. }
  37. }

控制台输出结果

  1. 1. 异步方法调用前. ThreadId:1
  2. 2. 异步方法开始. ThreadId:1
  3. 3. 异步方法结束. ThreadId:1
  4. 4. 异步方法内部开始. ThreadId:3
  5. 5. 异步方法调用后. ThreadId:1
  6. 6. 异步方法内部结束. ThreadId:3
  7. 7. 异步方法await结束. ThreadId:3
  8. 8. 来自异步方法内部的结果. ThreadId:3
  9. 9. 异步方法使用await后. ThreadId:3

分析

为了描述更方便,为每条输出都添加了序号。 为了更清晰的知道每一步的执行顺序以及所在的线程,均添加了ThreadId

  1. 第1条输出,主线程,没有什么特别的。
  2. 第2条输出,主线程,说明:调用异步方法本身并不会另起一个线程,如果这里面没有await的话,调用这个方法和调用普通方法没有任何区别。
  3. 第3条输出,主线程,说明:执行异步方法后主线程并没有被挂起,而是直接继续往下走。
  4. 第4条输出,线程3(代表子线程,不一定每次都是3),代码显示的要起用一个新线程,没有什么特别的。
  5. 第5条输出,主线程,和第3条一样,主线程继续往下走,只是代码在不同的方法里而已。
  6. 第6条输出,线程3,内部执行结束,没什么特别。
  7. 第7条输出,线程3,说明:这里有一个不同的地方,使用了await,可见,这里是子线程的延续
  8. 第8-9条输出,线程3,和第7条一样,延续了子线程。

变种

我们把ExcuteAsync方法里的await ret,改成ret.Result看看效果

  1. 1. 异步方法调用前. ThreadId:1
  2. 2. 异步方法开始. ThreadId:1
  3. 3. 异步方法结束. ThreadId:1
  4. 4. 异步方法内部开始. ThreadId:3
  5. 5. 异步方法调用后. ThreadId:1
  6. 6. 异步方法内部结束. ThreadId:3
  7. 7. 异步方法await结束. ThreadId:3
  8. 8. 来自异步方法内部的结果. ThreadId:1
  9. 9. 异步方法使用await后. ThreadId:1

第8-9条输出线程变了,可见是主线程被挂起了,等待子线程结束后继续往下执行。那么如果在AsyncMethod里也使用Result,效果又是什么样的?

我们把AsyncMethod方法里的await task改成task.Result,看输出结果

  1. 1. 异步方法调用前. ThreadId:1
  2. 2. 异步方法开始. ThreadId:1
  3. 3. 异步方法结束. ThreadId:1
  4. 4. 异步方法内部开始. ThreadId:3
  5. 5. 异步方法内部结束. ThreadId:3
  6. 6. 异步方法await结束. ThreadId:1
  7. 7. 异步方法调用后. ThreadId:1
  8. 8. 来自异步方法内部的结果. ThreadId:1
  9. 9. 异步方法使用await后. ThreadId:1

现在只有Task内部的输出是在子线程了。可见,使用Result的话会失去异步的效果,换句话说,使用Result就不再是异步调用了

附:文笔不好,只能用习惯的代码来描述,希望能给读者带来帮助。

aync await 进一步探索的更多相关文章

  1. Celery:进一步探索

    一.创建Celery专用模块 对于大型项目,一般需要创建一个专用模块,便于管理. 1.1 模块结构 proj/__init__.py /celery.py /tasks.py proj/celery. ...

  2. 进一步探索:Windows Azure 网站中解锁的配置选项

     编辑人员注释: 本文章由 Windows Azure 网站团队的项目经理 Erez Benari 撰写. 在 Windows Azure 网站 (WAWS) 中管理网站时,许多选项可使用 Azu ...

  3. Python标准库11 多进程探索 (multiprocessing包)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在初步了解Python多进程之后,我们可以继续探索multiprocessing包 ...

  4. c#之Async、Await剖析

    c#之Async.Await剖析 探索c#之Async.Await剖析 2015-06-15 08:35 by 蘑菇先生, 1429 阅读, 5 评论, 收藏, 编辑 阅读目录: 基本介绍 基本原理剖 ...

  5. [转] Async/Await替代Promise的6个理由

    Node.js 7.6已经支持async/await了,如果你还没有试过,这篇博客将告诉你为什么要用它. Async/Await简介 对于从未听说过async/await的朋友,下面是简介: asyn ...

  6. Hadoop2源码分析-RPC探索实战

    1.概述 在<Hadoop2源码分析-RPC机制初识>博客中,我们对RPC机制有了初步的认识和了解,下面我们对Hadoop V2的RPC机制做进一步探索,在研究Hadoop V2的RPC机 ...

  7. 每一行代码都有记录—如何用git一步步探索项目的历史

    每一行代码都有一块被隐藏了的文档信息. 下面的代码片段不管是谁写的,其第4行因为某些原因要访问一个DOM结点的clientLeft属性,但却对结果不作任何处理.这十分的莫名其妙,你能告诉我他们为什么要 ...

  8. 企查查app 初步探索

    企查查app sign算法破解初步探索 之前有说过企查查的sign的解密,但这次是企查查app的sign算法破解,目前是初步进程. 已删除!!!! 上边一些变量已经找到了,其中就有时间戳,其余两个需要 ...

  9. python_lesson2 多进程探索 (multiprocessing包)

    进程池 进程池 (Process Pool)可以创建多个进程.这些进程就像是随时待命的士兵,准备执行任务(程序).一个进程池中可以容纳多个待命的士兵.       import multiproces ...

随机推荐

  1. SocketServer模块

    在利用select实现伪并发的socket博文中我们说了: 如果要实现一个server端可以和多个客户端进行通信可以使用 1.多线程 2.多进程 3.select I/O多路复用 在那篇博文中我们介绍 ...

  2. 关于微信小程序图片失真的解决方案

    今天来说一说 关于微信小程序的图片失真问题的解决,微信小程序的image标签要设置其宽高,不然图片若宽高过大会撑开原始图片大小的区域:如下 但是宽高设置固定了会导致有些图片和规定显示图片大小的比例不一 ...

  3. Redis数据迁移方案

    场景 Redis实例A ---> Redis实例B,整库全量迁移 方案一: mac环境 brew install npm npm install redis-dump -g 针对RedisA: ...

  4. javascript 类型的判断

    在平常写js代码,类型判断必不可少,那么我们常见有哪几种?看到了标题,先不看你会想到那些方法 ,常用呢些呢?那么今天我自己总结一些判断类型的判断,如有错,万望告知! 1:typeof 常用这种方法不错 ...

  5. PRINCE2学习

    今天对PRINCE2中提及的7大主题进行学习,主要的内容是通过概述和PMBOK之间的对比做一些总结,每个主题所包含的过程和方法并没有太多涉及,没有对整个体系有全面深入的学习,有些断章取义的地方也请博友 ...

  6. 【C语言】判断三角形类型

    根据输入的三角形的三边判断三角形的类型,并输出其面积和类型. #include<stdio.h> #include<stdlib.h> #include<math.h&g ...

  7. String类的实现(4)写时拷贝浅析

    由于释放内存空间,开辟内存空间时花费时间,因此,在我们在不需要写,只是读的时候就可以不用新开辟内存空间,就用浅拷贝的方式创建对象,当我们需要写的时候才去新开辟内存空间.这种方法就是写时拷贝.这也是一种 ...

  8. Luogu1074靶形数独【启发式搜索】

    Luogu1074靶形数独 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, ...

  9. DCN路由操作

    offset */interface in/out access-list/prefix-list <1-16>                 // 修改路由偏移量   RIP偏移列表 ...

  10. Windows入门基础:1.关于CreateWindow()函数使用中遇到的问题

    我在实现显示窗口的程序中,遇到一个问题:首先程序没有任何语法错误,编译能够通过,但是就是不能弹出窗口. 后来在MSDN中查询CreateWindow()函数,发现了下面这句话: "If lp ...