await等待的到底是可等待对象中的什么?如何正确创建Task?
await 到底在等什么?——异步编程核心概念澄清
我查阅了大量该主题相关的技术资料,已梳理出异步编程的三个基本前提:
await的核心作用是将控制权从被调用方交还给调用方- 绝大多数现代I/O操作在底层架构实现中不会占用真实线程
- 绝大多数async方法不会显式启动自有线程(Web请求场景是典型代表)
本文重点围绕第三点展开说明,以下方C#代码作为示例:
public async Task<int> LongOperationWithAnInt32ResultAsync(string input) { /// Section A _ = int.TryParse(input, out var parsedInt) parsedInt = SyncOperationWithAnInt32Result(parsedInt); /// Section B await MyCustomTaskThatIWantAwaited(); /// Section C return parsedInt; } private Task MyCustomTaskThatIWantAwaited() { /// Section D AnotherSyncOperationWithVoidResult(); /// Section E return Task.CompletedTask; }
上述代码中的LongOperationWithAnInt32ResultAsync(string)方法会完全以同步方式执行,根本达不到异步实现的预期效果。
问题根源:执行到Section B的调用逻辑时,Section D、Section E的代码会被立即同步执行,完全不会被await挂起等待。如果移除Section D的代码,同时将Section E的返回逻辑替换为
return Task.Run(() => AnotherSyncOperationWithVoidResult()),执行逻辑就会发生变化:此时await跟踪的可等待对象变为Task.Run调度的执行单元,状态由返回的Task实例封装。
如果把Section B的代码替换为await Task.Delay(10000);或是await FunctionalWebRequestAsync();,就能实现预期的异步执行效果。但已知这两个方法内部都不会创建专门用于跟踪状态的专用线程——那么await等待的到底是什么?
注:我已经采纳了帮我厘清Task功能认知误区的主回答,也建议大家参考我本人补充的回答内容,大概率能找到需要的信息。
内容的提问来源于stack exchange,提问作者user18908005
相关产品推荐
相关产品推荐

