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,多么尴尬的一函数

你要知道多线程是干啥的。

把可以异步的耗时长的部分使用第二个线程去运行,减少对主线程的影响,保持应用响应、交互

最新文章

  1. [Network Analysis] 复杂网络分析总结
  2. linux学习第一天,常用命令一
  3. jQuery验证控件jquery.validate.js使用说明+中文API
  4. 只有在配置文件或 Page 指令中将 enableSessionState 设置为 true 时,才能使用会话状态。还请确保在应用程序配置的 // 节中包括 System.Web.SessionSta
  5. 113、ScrollView滑动到了最底部
  6. SAP-GR/IR的理解
  7. MVC中JQuery文件引入的路径问题,@Url.Content函数
  8. shell 编程中使用到得if语句内判断参数
  9. 杂乱无章之javascript(二)
  10. node.js 安装express 提示 command is not found
  11. js方法中的this
  12. kingso_module - Taocode
  13. /opt/apache-tomcat-7.0.57/conf/catalina.policy(权限不够)
  14. ASP.Net 获取Form表单值
  15. 【PowerDesigner】【4】连接数据库并生成ER图
  16. redis的repl-ping-slave-period和repl-ping-replica-period
  17. iOS 用自签名证书实现 HTTPS 请求的原理
  18. Hadoop 和 Spark 的关系
  19. 【转】MYSQL数据库设计规范与原则
  20. 判断URL是否支持断点续传?

热门文章

  1. 调用API函数减少c#内存占用(20+m减至1m以下)
  2. [VS]VS2017 安装ReportDesigner/ReportViewer的方法
  3. 【备忘】C#语言基础-1
  4. 可以用GetObjectProp来获取对象的属性
  5. Qt5.5.0在Linux下静态编译(加上-fontconfig编译项才能显示中文) good
  6. 类成员函数指针的特殊之处(成员函数指针不是指针,内含一个结构体,需要存储更多的信息才能知道自己是否virtual函数)
  7. 去除文件属性(使用SetFileAttributes API函数)
  8. 一个基于jQuery写的弹窗效果(附源码)
  9. Impala概念与架构
  10. 数据库读写分离Master-Slave