aync await 进一步探索

时间:2021-11-24 11:12:50

aync await 进一步探索

首先来个例子

class Program
{
static int index = 1;
static void Log(string str)
{
Console.WriteLine((index++) + ". " + str + ". ThreadId:" + Thread.CurrentThread.ManagedThreadId);
} static void Main(string[] args)
{
//解决.net core控制台输出中文乱码的代码
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
//async 不能用于Main方法,所以在这里单独使用一个方法来调用,各位可以试试,编译不过,但VS就是不会告诉你错误在哪里
ExcuteAsync();
Console.ReadLine();
} static async void ExcuteAsync() {
Log("异步方法调用前");
var ret = AsyncMethod();
Log("异步方法调用后");
Log(await ret);
Log("异步方法使用await后");
} static async Task<string> AsyncMethod() {
Log("异步方法开始");
var task = Task.Run<string>(() =>
{
Log("异步方法内部开始");
Thread.Sleep(3000);
Log("异步方法内部结束");
return "来自异步方法内部的结果";
});
Log("异步方法结束");
var ret = await task;
Log("异步方法await结束");
return ret;
}
}

控制台输出结果

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

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

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

1. 异步方法调用前. ThreadId:1
2. 异步方法开始. ThreadId:1
3. 异步方法结束. ThreadId:1
4. 异步方法内部开始. ThreadId:3
5. 异步方法内部结束. ThreadId:3
6. 异步方法await结束. ThreadId:1
7. 异步方法调用后. ThreadId:1
8. 来自异步方法内部的结果. ThreadId:1
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 多进程探索 &lpar;multiprocessing包&rpar;

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

  4. c&num;之Async、Await剖析

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

  5. &lbrack;转&rsqb; Async&sol;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&lowbar;lesson2 多进程探索 &lpar;multiprocessing包&rpar;

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

随机推荐

  1. build&sol;envsetup&period;sh 生成的命令详解表

    参考: https://wiki.cyanogenmod.org/w/Envsetup_help 它是一个.sh文件,用source后就生成android编译相关函数,具体如下. 速查 Invokin ...

  2. 委托、事件和Lambda

    一.委托 delegate1.在.Net平台下,委托类型用来定义和响应应用程序中的回调.事实上,.Net委托类型是一个类型安全的对象,指向可以以后调用的其他方法,.Net委托是内置支持多路广播和异步方 ...

  3. oc-26-动态类型检测

    /** 1).判断对象是不是指定类的对象或者指定类的子类对象. - (BOOL)isKindOfClass:(Class)aClass; 2).判断对象是不是1个特定类型的对象,不包括子类. - (B ...

  4. 当append里面的标签显示不出来的时候,用下面的方式做

     $("#result_td").append(tem1+tem3)  $("#result_td").append($(tem1+tem3)) 

  5. &commat;Valid springMVC bean校验不起作用及如何统一处理校验

    SpringMVC 使用JSR-303进行校验 @Valid 使用注解 一.准备校验时使用的JAR validation-api-1.0.0.GA.jar:JDK的接口: hibernate-vali ...

  6. Android取得电池的电量

    首先需要用到的是一个类继承BrocastReceiver 2 代码如下: public class Battery_Info extends BroadcastReceiver { @Override ...

  7. 基于jQuery的AJAX实现三级联动菜单

    最近学习jQuery,所以就写了一个关于中国省市县/区的三级联动菜单,权当相互学习,相互促进,特此记录. 下面是嵌套js的html文件: <!DOCTYPE html> <html ...

  8. windows PHP 安装 redis 外加扩展

    前置条件:为php7.2搭建redis扩展的前提是在本机上已经成功搭建好php的运行环境,我的电脑的运行环境时 apache2.4+mysql5.5+php7.2. 操作系统为64位,编译环境为Mic ...

  9. Mac OS 中安装 autoconf 和 automake

    在Mac上面编译FFmpeg需要安装很多东西,首先是:autoconf 和 automake 请按照以下顺序安装: curl -O http://mirrors.kernel.org/gnu/m4/m ...

  10. python记录&lowbar;day16 类的成员

    一.变量 1.实例变量(又叫字段.属性) 创建对象时给对象赋值 形式: self.xxx = xxx 访问: 对象名.xxx     只能由对象访问 class Person: def __init_ ...