电话
400 9058 355
ValueTask 仅在异步操作同步完成时比 Task 快,因其避免堆分配;若总是异步完成,则无优势甚至略慢。
和 task
ValueTaskValueTask 可以用栈上的结构体返回,而 Task 每次都 new 一个对象——这会触发 GC 压力。
常见同步完成场景包括: M(缓冲区有剩余)、
ChannelReader.TryRead(队列非空)、自定义 IValueTaskSource 实现的即刻完成 awaitable。
ValueTask 能显著降低 Gen0 GC 次数ValueTask 内部仍会创建 Task,额外多一层封装开销(微乎其微,但不占优).Result 或调用 .GetAwaiter().GetResult(),ValueTask 会 throw InvalidOperationException(已释放或未 await),而 Task 允许这样做(不推荐)ValueTask 是一次性值类型,设计上禁止重复 await 或多次消费。一旦 await 完成,内部持有的 IValueTaskSource 可能已被回收或重置;再次 await 会触发 ObjectDisposedException 或静默错误。
对比 Task:它是引用类型,可安全多次 await、存储到字段、传给多个消费者。
ValueTask 存入类字段:private ValueTask _cache;
var vt = GetDataAsync();
await vt;
await vt; // 可能崩溃
Task(调用 .AsTask()),再做后续操作Task 实现了 INotifyCompletion 和 ICriticalNotifyCompletion,也实现了 IDisposable(空实现);ValueTask 同样实现这些接口,但它的 IDisposable 是为防止误用而设的——调用 Dispose() 仅在它包装的是 IValueTaskSource 且尚未完成时才有效。
关键约束差异:
ValueTask 要求 T 必须是可默认构造的(where T : default 隐含),因为内部结构体需支持无参初始化;Task 无此限制ValueTask 使用 await foreach(除非它包装的是 IAsyncEnumerable);而 Task> 可以Task 支持 .ContinueWith()、.Wait()、.Result 等同步阻塞 API;ValueTask 不支持——必须先 .AsTask()
很多人误以为“高性能 API 就该返回 ValueTask”,其实选择依据是调用模式:
Stream.ReadAsync)→ 返回 ValueTask,因为使用者大概率 await 一次且重视分配Task,避免把 ValueTask 传播出去导致调用方踩坑Policy.WrapAsync(...).ExecuteAsync(...))→ 统一转 .AsTask(),否则策略库无法安全持有Task 更容易 fake(Task.FromResult),ValueTask 需要构造 ManualResetValueTaskSourceCore,麻烦得多最常被忽略的一点:ValueTask 的性能收益只在高吞吐、低延迟、同步完成比例高的服务中可测;普通 Web API 或命令行工具几乎感知不到,反而因误用引入隐蔽异常。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...