惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
有赞技术团队
有赞技术团队
T
The Blog of Author Tim Ferriss
F
Fortinet All Blogs
D
DataBreaches.Net
F
Full Disclosure
腾讯CDC
博客园 - 【当耐特】
MyScale Blog
MyScale Blog
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
Last Week in AI
Last Week in AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
爱范儿
爱范儿
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
SegmentFault 最新的问题
The Register - Security
The Register - Security
WordPress大学
WordPress大学
博客园 - 聂微东
雷峰网
雷峰网
J
Java Code Geeks
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Privacy International News Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
A
Arctic Wolf
Scott Helme
Scott Helme
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tor Project blog
博客园 - 三生石上(FineUI控件)
Know Your Adversary
Know Your Adversary
AWS News Blog
AWS News Blog
G
Google Developers Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
CERT Recently Published Vulnerability Notes
O
OpenAI News
Project Zero
Project Zero
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Application and Cybersecurity Blog
Application and Cybersecurity Blog
云风的 BLOG
云风的 BLOG
N
News and Events Feed by Topic
MongoDB | Blog
MongoDB | Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Microsoft Security Blog
Microsoft Security Blog
Cisco Talos Blog
Cisco Talos Blog
P
Palo Alto Networks Blog
Schneier on Security
Schneier on Security

博客园 - ProjectDD

NET 中 Async/Await 的演进:从状态机到运行时优化的 Continuation C# 指针用法小结 C# BinaryPrimitives 类 C# 内存对齐 linq 查询关于 from子句 关于排序算法 C# Dev Kit 经常导致崩溃 不太会用Span<T> 看文档上的优点估摸着试试 span,memory,ArrayPool,MemoryPool,等的性能对比 C# simd 性能雷点记录 C# 模式匹配里应该注意的几点 高中生理解梯度为何是方向导数极大值 概略 deep net 通过relu 进行函数逼近 win10 下安装 rust 的 依赖配置,通过vs2022 C# 有多需要aot 24个希腊字母的中文拼音版 英语发音探讨 sagemath 9.x 下的 jupyter 工作路径设置 Serializing delegates is not supported on this platform
关于C# await的一点新理解
ProjectDD · 2024-01-31 · via 博客园 - ProjectDD

关于await又理解深一点了,以前有点懵,
原来await 是对Task.Run的一个修饰(更准确的说是对Task实例的一个修饰,因为Task实例是必然会包装一个委托的所以就实现了对方法的包装,当这个方法调用时也就是Run时你可以选择是否使用await),叶节点,后续技节点是对标有async的方法进行串烧修饰,所以根在Task.Run这个方法要所以要理解await必须要详细查看Task.Run
Task.Run是调用后直接把Run的参数委托丢线程池的然后不等待直接返回的,所以返回是一个Task/Task<T>只有这两种情况加上await以后 就等待,然后直接取出Task<T>中的T了,这中间的各种可能的隐藏操作被底层编译器,运行时等代替了,比如线程上下文切换等。

要注意其实在实际场景中直接用Task.Run而不加await的情况才是异步的核心需求,异步的意思是同时做不等待。所以只有让很多Task同时开始调用的时候才有价值。

所以在同步调用方调用async方法时,最终还得用.Wait()/Result两种方式对其进行调用,从这里可以看出await其实是在异步线程池上进行的等待。因为现在有很多异步调用终端比如 webapi中的 Controller.Action方法比如 标记为async的Main方法都是异步调用终端所以不需要用上述方式切换回

同步主线程。

//...

async Task mAsync(){
    await Task1();
    await Task2();
    //...
    await Task3();
}

void m(){
    mAsync().Wait();
}

上述代码是有价值的异步设计为什么呢?因为mAsync方法里同时有多个await在,是await其实是在异步里等待它虽然在等待但是在异步里等待,这还有个好处是它可以在设计时清楚的管理异步调用的次序,要不然异步调用的次序是不可管理的要不然加很多锁或通知机制,而Task很好的把这些机制底层化为自动处理了,那么这些Task1...n之间的任务实际在调用m方法时会全部给到线程池(做统筹)从而能让它们可以在一定程度上“同步执行”来体现异步的价值,以至于在最后mAsync.Wait()时会有较短的耗时和较高的cpu资源利用率,而这就是异步编程的价值所在。

async Task m(){
  var time0=DateTime.Now;
  var t=Task.Delay(5000);
  await Task.Delay(2200);
  await Task.Delay(2500);
  await t;
  Console.WriteLine(DateTime.Now - time0);
}
await m();

// 有网友给出的代码经测试结果发现其耗时基本上在5秒多一点,而如果3个await同步执行的话需要9.7秒以上,这大概是因为这3个await之间没有依赖不会Task.ContinueWith(OtherTask)的原因如果存在这样的依赖那么时间就会是9.7以上,所以底层应该对此做了判断,这也就是说在async方法里要多用Task.Run,只要保证其中有一个await就行,await的目的是 Task.ContinueWith 让其返回可以被拿到调用环境里使用否则,则不需要await 而如果async方法有很多Task.Run但其实并不都需要await,只是你写了也无妨因为底层有一定的判断是知道的(上述测试结果就是证明),所以你可以都写,也可以只在最后一个Task.Run()前写await以满足async方法的需要。这样的设计就真正能体现异步编程带来的价值了。