async与await详解
async和await只是编译器功能。编译器会用Task类创建代码。如果不适用这两个关键字,也可以用C#4.0和Task类实现同样的功能,只是没有那么方便。
题主在概念上确实混淆的不行,但是确实async/await这个东西继承了我软从VB6开始的光荣传统(易学难精)。工作中确实没有碰到几个真正搞的明白的同事(轮子哥,I大这种论外)。
首先,题主需要搞明白一个概念,就是async不是函数声明的一部分。从调用者的角度来看,不存在async这个东西。
async是一个专门给编译器的提示,意思是该函数的实现可能会出现await。async并不是表明这个方法是异步方法,而是标明这个方法里有异步调用。至于为啥要有这个提示,而不是编译器发现函数实现里有await的时候就自动加上async标志,这是定义语言标准时的选择,C#(这个feature)的作者也许认为这样写让作者更明确的意识到自己在实现一个包含异步调用的函数。(我瞎猜的)
下面举两个例子
Task<int> DelayAndCalculate1(int a, int b)
{
return Task.Delay(1000).ContinueWith(t => a + b);
}
async Task<int> DelayAndCalculate2(int a, int b)
{
await Task.Delay(1000);
return a + b;
}
这两个函数(不算函数名的不同),在函数声明上是完全没有区别的。只是其中一个在实现中使用了await,所以C#语法要求我们必须在标示async。
从调用者的角度来看,这两个函数完全一致(而且行为也一致),都可以使用await关键词unwrap Task类型的返回值(其实这里有一个叫做GetAwaiter的约定,这里不展开说)。
另一个佐证就是interface的定义中不能写async,因为如上所述,async不是函数声明,而其实编译函数实现的提示。
&amp;lt;img src="https://pic2.zhimg.com/50/v2-9a4354b91340bde2391e5b6406c05eb2_hd.jpg" data-rawwidth="680" data-rawheight="221" class="origin_image zh-lightbox-thumb" width="680" data-original="https://pic2.zhimg.com/v2-9a4354b91340bde2391e5b6406c05eb2_r.jpg"&amp;gt;
最后回到题主的问题为啥有了async还要写await,其实真正重要的是await(和其他异步的实现,如例子中的DelayAndCalculate1),有没有async反而确实不重要。
那么可不可以如题主所说的设计一个语法糖,不需要写Task<int>而写async int呢?答案是当然可以这么设计,但这就只是单纯的让编译器自动把async int翻译成Task<int>而已,C#的作者单纯没有这么设计而已(因为这会使得函数的返回值和声明时不同,我个人也觉得这会导致更大的confusion)。因为一个返回Task<int>的函数,不只可以用来await,还有很多别的玩法,语言应该给予开发人员解开和不解开的自由。最简单的例子:
async Task<int> ComplexWorkFlow()
{
Task<int> task1 = DoTask1();
Task<int> task2 = DoTask2();
Task<int> task3 = DoTask3UseResultOfTask1(await task1);
Task<int> task4 = DoTask4UseResultOfTask2(await task2);
return await DoTask5(await task3, await task4);
}
我用短短几行实现了一个相对复杂的工作流,task直接的dependency很明确的表达在代码里,并且task1和task2可以并行执行,task3和task4可以并行执行(事实上更好的写法可以让task1->task3完全并行与task2->task4)。核心思路就是只有当某个task的执行结果需要被使用的时候才解开这个task的值(等它执行完毕)。
我觉得题主你没搞清楚多线程和异步的概念。
对应不同的需求,有很多种多线程执行方法的。async/await只是其中的一种,这种方法叫做异步调用。举个栗子吧,你的老板让你搬走一千箱货,你叫来一千个民工每人搬1箱,不管他搬没搬到指定地点,这个是Task.Run()。你让人搬到指定地点领根签子回来找你领钱,这个就是async/await。为啥要await?因为你要等着收回签子发钱啊,把应发的钱发完这事才算完呢。如果你只需一声令下:搬走!然后就可以拍拍屁股走人的话,就不要和人说什么要领签子回来换钱的话嘛。
因为这个函数你是想要在中途出现异步的,就是在await的地方创建新线程继续执行往后的代码,旧线程返回回去干该干的事去
结果你这函数里没有await,多么尴尬的一函数
你要知道多线程是干啥的。
把可以异步的耗时长的部分使用第二个线程去运行,减少对主线程的影响,保持应用响应、交互
async与await详解的更多相关文章
- async和await详解
async和await详解 1.非UI线程中执行 Test()函数带有async 和await ,返回值写成Task. 1 using System; 2 using System.Threadin ...
- Promise和async await详解
本文转载自Promise和async await详解 Promise 状态 pending: 初始状态, 非 fulfilled 或 rejected. fulfilled: 成功的操作. rejec ...
- JavaScript中的async/await详解
1.前言 async函数,也就是我们常说的async/await,是在ES2017(ES8)引入的新特性,主要目的是为了简化使用基于Promise的API时所需的语法.async和await关键字 ...
- C#多线程和异步(二)——Task和async/await详解
一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...
- C#多线程和异步(二)——Task和async/await详解(转载)
一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...
- 关于async function(){ let res = await } 详解
本文引自: https://www.jianshu.com/p/435a8b8cc7d3 async function fn(){ //表示异步,这个函数里面有异步任务 let result = aw ...
- Task和async/await详解
一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...
- C#多线程和异步——Task和async/await详解
阅读目录 一.什么是异步 二.Task介绍 1 Task创建和运行 2 Task的阻塞方法(Wait/WaitAll/WaitAny) 3 Task的延续操作(WhenAny/WhenAll/Cont ...
- async await详解
async await本身就是promise + generator的语法糖. 本文主要讲述以下内容 async awiat 实质 async await 主要特性 async await 实质 下面 ...
随机推荐
- Spring Web Flow 的优缺点
# 前言 Spring Web Flow = SWF 最近学习了<Spring实战>的第八章,Spring Web Flow.感觉是个不错的东西.无奈发现网上的资料少之又少.后来发现根本没 ...
- ORM 集合
1.EF https://github.com/aspnet 2.Chloe.ORM http://www.cnblogs.com/so9527/p/5809089.html http://www ...
- This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed.
Attempt to load Oracle client libraries threw BadImageFormatException. This problem will occur when ...
- 如何快速生成数据文件(fsutil命令,使用CreateFile和SetEndOfFile API函数,fopen和fseek RTL函数)
1. fsutil 命令 文件会瞬间生成,因为实际上Windows只是分配了名称.地址和空间给该文件,并没有读写任何文件内容 100M=1024x1024x100 fsutil file create ...
- 【全面解禁!真正的Expression Blend实战开发技巧】第八章 FluidMoveBehavior完全解析之一漂浮移动
原文:[全面解禁!真正的Expression Blend实战开发技巧]第八章 FluidMoveBehavior完全解析之一漂浮移动 好久没更新博客了,今天如果没急事,准备连发三篇,完全讲解Blend ...
- QLocalServer与QLocalSocket进程通讯
在Qt中,提供了多种IPC方法,作者所用的是QLocalServer和QLocalSocket.看起来好像和Socket搭上点边,实则底层是windows的name pipe.这应该是支持双工通信的. ...
- SQL之连接查询
这几天忙着笔试.面试,遇到了好几个关于数据库的试题,当然只是简单的多表查询.我第一时间都是选择select...from...where...group by...having...这个结构去写的.但 ...
- winform窗体绑定监控键盘事件
直接注册是触发不了的, 例如: 总是不能触发. 需要在窗体设置一直属性: 大概意思是在无论窗体的那个子元素获得焦点,都将触发监控键盘的事件.
- 解决xp越来越慢的办法(其中有些自动备份的功能)
1.减少磁盘空间占用2.终止不常用的系统服务3.安全问题4.另外一些技巧 首先问一下,你是不是很想激活XP,不...准确的说你是不是想在ms的站上能够升级.如果答案是肯定的话,那我们就先来探讨一下安装 ...
- string与QString转换(string既可以是utf8,也可以是gbk)
AtUtf8.h #ifndef _QT_UTF8_H #define _QT_UTF8_H #include <QString> #include <string> usin ...