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;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;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详解的更多相关文章

  1. async和await详解

     async和await详解 1.非UI线程中执行 Test()函数带有async 和await ,返回值写成Task. 1 using System; 2 using System.Threadin ...

  2. Promise和async await详解

    本文转载自Promise和async await详解 Promise 状态 pending: 初始状态, 非 fulfilled 或 rejected. fulfilled: 成功的操作. rejec ...

  3. JavaScript中的async/await详解

    1.前言 ​ async函数,也就是我们常说的async/await,是在ES2017(ES8)引入的新特性,主要目的是为了简化使用基于Promise的API时所需的语法.async和await关键字 ...

  4. C#多线程和异步(二)——Task和async/await详解

    一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...

  5. C#多线程和异步(二)——Task和async/await详解(转载)

    一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...

  6. 关于async function(){ let res = await } 详解

    本文引自: https://www.jianshu.com/p/435a8b8cc7d3 async function fn(){ //表示异步,这个函数里面有异步任务 let result = aw ...

  7. Task和async/await详解

    一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...

  8. C#多线程和异步——Task和async/await详解

    阅读目录 一.什么是异步 二.Task介绍 1 Task创建和运行 2 Task的阻塞方法(Wait/WaitAll/WaitAny) 3 Task的延续操作(WhenAny/WhenAll/Cont ...

  9. async await详解

    async await本身就是promise + generator的语法糖. 本文主要讲述以下内容 async awiat 实质 async await 主要特性 async await 实质 下面 ...

随机推荐

  1. WPF VisualTreeHelper的使用

    <Window x:Class="MyWpf.MainWindow"        xmlns="http://schemas.microsoft.com/winf ...

  2. js table鼠标点击时变色

    <head>    <title></title>    <script type="text/javascript">      ...

  3. String 源码分析

    Java 源码阅读 - String String 类型看起来简单,实际上背后的复杂性基本可以涵盖了整个 Java 设计,涉及到设计模式(不可变对象).缓存(String Pool 的理念).JVM( ...

  4. 使用ServiceStack.Redis实现Redis数据读写

    原文:使用ServiceStack.Redis实现Redis数据读写 User.cs实体类 public class User { public string Name { get; set; } p ...

  5. C++和QML混合的QT程序调试方法

    以前调试只是QML或者只是C++的QT程序很简单,断点打上,直接debug按钮一点,喝一口水,自然就停在断点了. 这次遇到C++和QML混合的程序,把CONFIG+=declarative_debug ...

  6. Unpaired/Partially/Unsupervised Image Captioning

    这篇涉及到以下三篇论文: Unpaired Image Captioning by Language Pivoting (ECCV 2018) Show, Tell and Discriminate: ...

  7. UWP入门(三) -- StackPanel与Grid的区别

    原文:UWP入门(三) -- StackPanel与Grid的区别 ##1.Grid 下布局 <Grid Background="{ThemeResource ApplicationP ...

  8. UWP入门(十一)--使用选取器打开文件和文件夹

    原文:UWP入门(十一)--使用选取器打开文件和文件夹 很漂亮的功能,很有趣 重要的 API FileOpenPicker FolderPicker StorageFile 通过让用户与选取器交互来访 ...

  9. 程序的开机关机重启,开机启动,休眠功能delphi实现(使用AdjustTokenPrivileges提升权限)

    TShutDownStatus = (sdShutDown,sdReboot,sdLogOff,sdPowerOff); procedure ShutDown(sdStatus : TShutDown ...

  10. Git基本用法(一)

    使用Git正常的工作流 创建/修改文件 使用git add <file1> <file2> <file3>...将文件添加至本地的缓冲区Index中 使用git c ...