检查ValueTask.IsCompleted对性能是否必要?两种写法性能对比
ValueTask.IsCompleted 检查是否有必要?性能对比分析
这个问题问到点子上了——很多人刚接触ValueTask的时候都会纠结要不要手动做IsCompleted检查,毕竟它的设计初衷就是减少同步完成场景下的开销。咱们一步步拆解来看:
先搞懂编译器对await ValueTask的处理
其实你写await DoAsync()的时候,编译器生成的代码已经自动帮你做了IsCompleted检查!它会先判断这个ValueTask是否已经完成:
- 如果同步完成,直接取出
Result,完全没有异步调度的开销; - 如果没完成,才会进入真正的异步等待流程,和普通Task的await逻辑一致。
两种实现的性能对比
内存维度
- 当
DoAsync()同步完成时:两种写法都不会分配额外的Task对象(ValueTask的核心优势就是这里),内存开销完全一样; - 当
DoAsync()异步完成时:两种写法最终都会走相同的异步等待路径,内存上也没有差异。
CPU维度
task.IsCompleted是一个非常轻量的字段读取操作,但问题在于——编译器已经帮你做了这个判断,你手动再写一遍,本质上是重复执行了一次无意义的检查,虽然CPU开销几乎可以忽略,但完全没必要,属于画蛇添足。
什么时候手动检查IsCompleted才有意义?
只有当你在获取结果之前,还有同步逻辑可以提前执行的时候,手动检查才有价值。比如:
var task = DoAsync(); if (task.IsCompleted) { // 同步完成时,直接做一些不需要等待的预处理逻辑 PreprocessSync(task.Result); } else { // 异步等待时,可以做一些异步预处理 await PreprocessAsync(); var result = await task; }
但如果只是单纯为了获取结果,像你给出的case2那样,完全是冗余操作。
结论
- case2的手动
IsCompleted检查不会带来任何性能提升,反而增加了代码复杂度; - 直接用case1的
bool result = await DoAsync()就足够了——编译器已经帮你做了最优的性能处理,代码还更简洁易读。
内容的提问来源于stack exchange,提问作者ALittleDiff
相关产品推荐
相关产品推荐

