dotnet 开发 API 的时候使用 asyn 、await 有什么优势吗

2019-11-06 15:44:22 +08:00
 daijinming

如果一个 API 被标记为 asyn,和 没有 asyn 的 api 有什么区别?不是太理解,这个和多线程有关系吗,求教

3917 次点击
所在节点    程序员
29 条回复
darkalien
2019-11-06 15:54:44 +08:00
darkalien
2019-11-06 16:02:27 +08:00
关于 async await 的理解,另推荐自己的文章:异步编程关键字 Async 和 Await - https://www.cnblogs.com/AlienXu/p/9529541.html
hihipp
2019-11-06 16:16:10 +08:00
服务器上的 async 有一篇官方文章说过,很久了,知识还是可用的,是从线程池说起的。

英文原文: https://msdn.microsoft.com/en-us/magazine/dn802603.aspx?f=255&MSPPError=-2147217396
中文: https://msdn.microsoft.com/zh-cn/magazine/dn802603.aspx?f=255&MSPPError=-2147217396
loqixh
2019-11-06 16:27:04 +08:00
await 本质就是通过编译器变化的无栈协程, 和 go 的协程是一样的, 其它的说法都是往复杂里扯
secondwtq
2019-11-06 19:05:33 +08:00
@loqixh Go 是 ”stackful“ 的吧 ...
”stackless“ 的有 JavaScript,C++,Kotlin,一大堆 ...
loqixh
2019-11-06 19:11:18 +08:00
@secondwtq 对 但是效果一样, 只是实现方法的区别
tinkerer
2019-11-06 19:22:51 +08:00
tinkerer
2019-11-06 19:23:54 +08:00
sorry, 误操作, 十分抱歉, 上一条与此贴无关
seakingii
2019-11-06 21:28:14 +08:00
你可以理解为在 await 的地方中断执行,在其它线程执行,执行完成后再返回 await 处,继续执行后面的代码.

和没有 async,await 的版本相比,就是提高了系统的并发量
seakingii
2019-11-06 21:29:30 +08:00
另外以前是没有 async,await 机制的,要写类似的代码,需要自己写线程,或者利用线程池什么的.代码和现在比起来复杂的多.
Presbyter
2019-11-06 21:47:47 +08:00
编译器的语法糖,可以更方便的使用线程池进行多线程应用开发.
MonoLogueChi
2019-11-06 23:51:20 +08:00
这个是异步编程,可以减少阻塞。另外 async 只是标记这个方法里可能会出现 await,在编译时没有实际作用,你也可以标记 async 而不写 await,这样编译也能过,只是 IDE 会提示你不要这样写。
lbp0200
2019-11-07 00:21:35 +08:00
关键字放在这里,让人感觉怪怪的
luozic
2019-11-07 02:45:34 +08:00
核心是现在大部分的应用是 IO 密集,实际就是 curd 密集型应用;
xuanbg
2019-11-07 09:11:23 +08:00
异步模式的好处就是可以同时进行多项任务,减少任务的总时间。就像做饭一样,没人会等电饭煲做好饭再开始炒菜。都是做饭(async)、炒菜(async)并行的,最后饭和菜都好了(await),就能吃了。
xingheng
2019-11-07 11:12:51 +08:00
@xuanbg 这个🌰好。但是如果有客人(request)就点了一个蛋炒饭(async),这样的话我觉得 sync 版的蛋烧饭会比 async 版的蛋炒饭更快,因为没有切换线程的损耗了。

关于楼上提到的并发量提高的问题我有些质疑,一个 request 在发起到完成之前,这个 working thread 应该是一直存在的,并不会因为 async 的使用导致 working thread dispose 或者 reuse 的情况。

我的理解对吗?
crclz
2019-11-07 12:57:05 +08:00
@xingheng 这个 working thread 不能说时一直存在的。
假如我调用 await GetDishAsync(),那么 GetDishAsync 任务所用到的线程会被高效管理。
好了,现在问题就来了:GetDishAsync 的 caller 所在的线程(你提到的 working thread )是否会一直存在?
不是的。因为 await GetDishAsync()的 caller 一定是一个 async 方法,它的线程资源一样会被高效管理。
xingheng
2019-11-07 13:30:50 +08:00
@crclz 有理。那我们再往下(main thread)追溯,(我没有写过 c#服务端,从其他语言推断的),main thread 或者说函数入口一定是 sync,每一个从 port 过来的请求一定是在 c#服务端对应一个 working thread 的,高效管理是语言级的特性,但是 working thread 的数量一定是不会减少的,working thread 之间(对外)也没有依赖关系,所以并发量还是没有增大。

我上面的蛋炒饭(async)假定确实很 critical,全程只有一个 async task 的需求是非常少见的,async 在这种情况下应该是没有什么好处的,高效管理只是说损耗很小,但不是没有。

async 在设计层面上是成功的,也推荐使用。在 API 设计层面上我觉得只是相对提高了响应请求处理的单位时间,勉强上可以说是间接地提高了并发量。

请指正。
xuanbg
2019-11-07 14:19:40 +08:00
@xingheng 并发量是会提高的。系统在同一时间能处理的 request 数量是和 CPU 的核数是一致的。那么,每个 request 的处理时间越短,“单位时间”内能处理的 request 数量就越多。请注意,我们正常情况下说的并发量,都是指「单位时间内的 request 处理数量」。
xuanbg
2019-11-07 14:26:25 +08:00
@xingheng 上面的说法可能还不是太准确。事实上,在 CPU 满负荷的情况下,异步并不一定能够提高效率。甚至有可能因为线程切换而导致效率下降。而正常情况下,CPU 负荷是需要控制在 60%以下的。这个时候,异步基本上都能提升处理效率。当然,CPU 的也负载会比同步更高一些。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/616879

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX