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 实质 下面 ...
随机推荐
- 定长文本格式编辑神器 - Record Editor
由于项目里有系统使用的是定长的文本格式,如果列数比较多的话编辑检查起来会特别麻烦.之前也找了各种编辑器的插件,最多只能显示列宽.辅助线而以还是不方便 .最后发现了一个开源项目 Record Edito ...
- win32Helper
点击别的winform窗口的按钮 #region 点击别的窗口的按钮 [DllImport("user32.dll", EntryPoint = "FindWindowA ...
- 自动启动 Windows 10 UWP 应用
原文: https://docs.microsoft.com/zh-cn/windows/uwp/xbox-apps/automate-launching-uwp-apps 简介 开发人员有多种选项可 ...
- 使用checkpoint做代理服务器
version:R80.30 T200 Step 1:编辑刀片的属性,开启http/https代理,如下图: Step 2:配置访问策略,如下图: Step 3:配置客户端浏览器如下图: Step 4 ...
- Win8Metro(C#)数字图像处理--2.5图像亮度调整
原文:Win8Metro(C#)数字图像处理--2.5图像亮度调整 2.5图像亮度调整函数 [函数名称] 图像亮度调整函数BrightnessAdjustProcess(WriteableBit ...
- WPF获取和设置应用程序范围的资源
设置资源: Application.Current.Resources["ApplicationScopeResource"] = Brushes.White; 使用代码获取资源: ...
- vmstat命令浅析
vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况.这个命令是我查看Linux/Unix最 ...
- SQLDirect 6.5 Source (Delphi 5-10.1 Berlin)
Description:SQLDirect Component Library is a light-weight Borland Database Engine replacement for Bo ...
- 关于git远程分支操作
对于用户来说,git给人提交到本地的机会.我们可以在自己的机器上创建不同的branch,来测试和存放不同的代码. 对于代码管理员而言,git有许多优良的特性.管理着不同的分支,同一套源代码可以出不一样 ...
- 针对TianvCms的搜索优化文章源码(无版权, 随便用)
介绍: 搜索优化虽然不是什么高深的技术, 真正实施起来却很繁琐, 后台集成搜索优化的文章可以便于便于管理, 也让新手更明白优化的步奏以及优化的日常. 特点: 根据自己的经验和查阅各种资料整理而成, 相 ...