.net 中的async,await理解
理解:
1、async修饰的方法可理解为异步方法(必须要配合await,否则和普通方法无异)
2、当async方法执行遇到await,则立即将控制权转移到async方法的调用者
3、由调用者决定是否需要等待async方法执行完再继续往下执行
4、await会挂起当前方法,即阻塞当前方法继续往下执行,转交控制权给调用者
注意:如果调用一个async方 法,却不使用await关键字来标记一个挂起点的话,程序将会忽略async关键字并以同步的方式执行。编译器会对类似的问题发出警告。
例子一:(控制台程序)
static void Main(string[] args)
{
MyMain();//由于main方法无法定义成async,顾此定义一个方法MyMain来表示main方法。
Console.Read();
}
static async void MyMain()
{
Console.WriteLine("main方法开始执行");
AsyncAction();
Console.WriteLine("main方法继续执行");
Console.WriteLine("main方法执行结束");
} static async Task<string> AsyncAction()
{
Console.WriteLine("AsyncAction方法await之前");
string result = await Task<string>.Run(() =>
{
Thread.Sleep();
Console.WriteLine("AsyncAction方法sleep一秒后");
return "AsyncAction的返回值";
});
Console.WriteLine("AsyncAction方法await之后-{0}", result);
return result;
}
执行结果:
由返回结果可以知,此异步方法AsyncAction执行遇到await,即程序执行到此行立刻被挂起,将控制权限交给MyMain方法,由MyMain决定是否等待AsyncAction执行完再往下执行,此处由于执行AsyncAction方法前不加await,所以直接往下执行。而AsyncAction方法中的await Task.Run(包括)后的代码会异步执行。
例子二:例子一中MyMain方法执行AsyncAction前面加await
static void Main(string[] args)
{
MyMain();//由于main方法无法定义成async,顾此定义一个方法MyMain来表示main方法。
Console.Read();
}
static async void MyMain()
{
Console.WriteLine("main方法开始执行");
await AsyncAction();
Console.WriteLine("main方法继续执行");
Console.WriteLine("main方法执行结束");
} static async Task<string> AsyncAction()
{
Console.WriteLine("AsyncAction方法await之前");
string result = await Task<string>.Run(() =>
{
Thread.Sleep();
Console.WriteLine("AsyncAction方法sleep一秒后");
return "AsyncAction的返回值";
});
Console.WriteLine("AsyncAction方法await之后-{0}", result);
return result;
}
执行结果:
由于AsyncAction方法执行前加了await,故MyMain方法要等待其执行结束才继续往下执行。
使用场景及用法分析:
当有某一操作执行时间较长或者执行结果对整体程序执行影响不大(一般此操作都会是一个独立一个方法。)主线程的执行不依赖于此操作的执行结果。
常见于一些IO操作,如日志的记录,当触发记录日志动作的时候,应该让其独立一个线程去执行,此时不管日志记录成功与否,
都不应该阻塞主线程的执行。
在上面的例子一中,可以将AsyncAction方法中的 Task.Run 当成记录日志的动作,当程序执行到 await Task.Run后,
AsyncAction方法立刻被挂起,主线程MyMain继续往下执行。
这里可能有人会疑问?为何不直接在主线程MyMain中直接开启线程 Task.Run 来记录日志?
而是要定义到一个异步方法(此例子为AsyncAction方法)中处理日志。
是,如果此时只是为了记录日志,也不是必须要写到一个方法中。但是,
首先,这种单一功能的操作,本应该就是独立写到一个方法中。
其次是 AsyncAction方法 中的 await Task.Run 的返回值也许还有其他操作。
如下面例子:记录日志之前,需要获取登陆用户的一些信息,并且将用户信息一同保存到日志中,如果写到主线程MyMain中,则避免不了阻塞主线程(因为需要等待获取用户信息)。
当然,你也可以将这两个方法一起写到一个方法中由Task调用,这里只是举个例子来说明Async和await的用法场景。
static void Main(string[] args)
{
MyMain();//由于main方法无法定义成async,顾此定义一个方法MyMain来表示main方法。
Console.Read();
}
static async void MyMain()
{
Console.WriteLine("main方法开始执行");
WriteUserLog();
Console.WriteLine("main方法继续执行");
Console.WriteLine("main方法执行结束");
} static async void WriteUserLog()
{
Console.WriteLine("获取用户信息之前");
string userInfo = await GetUserInfoAsync(); //尽量早的使用await,以便此方法尽快挂起(异步执行)
Console.WriteLine("写入日志之前");
WriteLog(userInfo);
} static Task<string> GetUserInfoAsync()
{
return Task.Factory.StartNew(() => {
Thread.Sleep();
Console.WriteLine("获取用户信息完成");
return "jxf";
});
} static void WriteLog(string userInfo)
{
Thread.Sleep();
Console.WriteLine("写入日志完成,用户信息:{0}", userInfo);
}
执行结果:
.net 中的async,await理解的更多相关文章
- 理解ES7中的async/await
理解ES7中的async/await 优势是:就是解决多层异步回调的嵌套 从字面上理解 async/await, async是 "异步"的含义,await可以认为是 async w ...
- 理解C#中的 async await
前言 一个老掉牙的话题,园子里的相关优秀文章已经有很多了,我写这篇文章完全是想以自己的思维方式来谈一谈自己的理解.(PS:文中涉及到了大量反编译源码,需要静下心来细细品味) 从简单开始 为了更容易理解 ...
- 【TypeScript】如何在TypeScript中使用async/await,让你的代码更像C#。
[TypeScript]如何在TypeScript中使用async/await,让你的代码更像C#. async/await 提到这个东西,大家应该都很熟悉.最出名的可能就是C#中的,但也有其它语言也 ...
- 在现有代码中通过async/await实现并行
在现有代码中通过async/await实现并行 一项新技术或者一个新特性,只有你用它解决实际问题后,才能真正体会到它的魅力,真正理解它.也期待大家能够多分享解一些解决实际问题的内容. 在我们遭遇“黑色 ...
- ES7前端异步玩法:async/await理解 js原生API妙用(一)
ES7前端异步玩法:async/await理解 在最新的ES7(ES2017)中提出的前端异步特性:async.await. 什么是async.await? async顾名思义是“异步”的意思,a ...
- [C#] .NET4.0中使用4.5中的 async/await 功能实现异
好东西需要分享 原文出自:http://www.itnose.net/detail/6091186.html 在.NET Framework 4.5中添加了新的异步操作库,但是在.NET Framew ...
- 在Silverlight中使用async/await
现在 async/await 大行其道,确实,有了 async/await ,异步编程真是简单多了,个人觉得 async/await 的出现,给开发者还来的方便,绝不亚于当年 linq 的出现. 但要 ...
- [C#] .NET4.0中使用4.5中的 async/await 功能实现异步
在.NET Framework 4.5中添加了新的异步操作库,但是在.NET Framework 4.0中却无法使用.这时不免面临着抉择,到底是升级整个解决方案还是不使用呢? 如果你的软件还没发布出去 ...
- js循环中使用async/await踩过的坑
最近写koa的时候遇见需要在循环中使用async/await的情况,当然第一反应就是直接上forEach,然后就直接翻车了... 直接上代码: function handleSql(val) { re ...
随机推荐
- 在angularJs实现批量删除
原理:在js中定义一个数组,然后给每个复选框一个点击事件,点击事件的方法参数有两个,一个是事件源$event,一个是id.点击复选框根据事件源判断是否被选中,然后进而是向这个数组增加或者删除id. $ ...
- Linux之chkconfig命令
chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法:chkconfig [--ad ...
- JMS学习(四)-一个简单的聊天应用程序分析
一,介绍 本文介绍一个简单的聊天应用程序:生产者将消息发送到Topic上,然后由ActiveMQ将该消息Push给订阅了该Topic的消费者.示例程序来自于<JAVA 消息服务--第二版 Mar ...
- 将本地的mongodb迁移到阿里云
首先在阿里云上安装mongodb,可以根据官方教程 https://docs.mongodb.com/manual/tutorial/install-mongodb-on-amazon/ 完成之后启动 ...
- 机器学习&深度学习视频资料汇总
第一部分 基础语言 pandax视频教程 链接: https://pan.baidu.com/s/1pLqavVX 密码: fath python入门到精通 链接: https://pan.b ...
- HTTP 错误 404.0 - Not Found
当网上的那些修改程序池的方法,无法解决此问题时,可以尝试修改以下的参数: 1.控制面板-->程序-->启用或关闭Windows功能--> Internet Information S ...
- Javascript - Vue - 过滤器
过滤器 输出的数据由vue对象提供,但它的数据可能需要做进一步的处理才适合展示给用户看,为此,可以在静态的Vue上定义一个过滤器对实例vue对象的data数据进行过滤处理. //调用过滤器//msg是 ...
- 分模块开发创建dao子模块——(七)
1.选中父工程右键新建maven module
- nodejs 配置服务自启动
1安装包 输入以下命令,安装需要的包 npm install node-windows -g 2编写自启动js 在目标server.js目录下新建auto_start_nodejs.js文件,将以下j ...
- expect学习笔记及实例详解【转】
1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示:1.1 首行加上/usr/bin/expect1.2 spawn: 后面加上需要执行的shell命令,比如说sp ...