c# IValueTaskSource 是什么 c#如何实现自定义ValueTask

发布时间 - 2026-01-28 00:00:00    点击率:
ValueTask 不是轻量级 Task,而是可选异步结果容器,其背后要么是 Task,要么是 IValueTaskSource 实现;后者仅用于高性能库底层,需手动控制状态机,业务代码不应自行实现。

ValueTask 不是“轻量级 Task”,而是可选的异步结果容器

直接说结论:ValueTask 本身不是 awaitable 的“实现”,它只是一个包装器,背后要么持有一个 Task,要么持有一个实现了 IValueTaskSource 的对象。只有当你要**完全绕过 Task 分配、手动控制异步状态机流转**时,才需要实现 IValueTaskSource —— 这不是日常开发该碰的东西,而是为高性能库(如 System.IO.PipelinesMicrosoft.Extensions.Caching)底层服务的机制。

IValueTaskSource 是什么:一个极简但危险的异步状态契约

IValueTaskSource 是一个仅含 5 个成员的接口,它把 await 行为拆解成纯方法调用:谁来决定是否已完成、如何获取结果、怎么注册回调、怎么触发完成。它不依赖 ThreadPoolSynchronizationContext,一切由你控制。

关键点:

  • Version 字段必须每次完成时递增,否则 ValueTask 会因版本不匹配而抛出 InvalidOperationException
  • GetResult(short token) 必须只被调用一次,且仅在 IsCompleted 返回 true 后;若未完成就调用,行为未定义
  • OnCompleted 注册的回调,必须在你调用 SetResult / SetException 时被同步或异步执行 —— 且必须严格匹配传入的 token
  • 你必须自己管理线程安全:多个线程可能并发调用 OnCompletedSetResult

手写一个最简 IValueTaskSource:只支持成功、无取消、单次使用

下面是一个仅用于演示的最小可行实现,它模拟“稍后返回一个 int”。注意:它不处理取消、不支持重用、不保证线程安全(仅作原理示意):

public sealed class SimpleIntSource : IValueTaskSource
{
    private int _result;
    private short _version;
    private Action? _continuation;
    private object? _state;

    public int GetResult(short token)
    {
        if (token != _version) throw new InvalidOperationException("Invalid token");
        return _result;
    }

    public ValueTaskSourceStatus GetStatus(short token) => 
        token == _version ? ValueTaskSourceStatus.Succeeded : ValueTaskSourceStatus.Pending;

    public void OnCompleted(Action continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
    {
        _continuation = continuation;
        _state = state;
    }

    public void SetResult(int result)
    {
        _result = 

result; _version++; _continuation?.Invoke(_state); } public void SetException(Exception error) => throw new NotSupportedException(); public short Version => _version; }

用法示例:

public static ValueTask DelayedInt() {
    var source = new SimpleIntSource();
    _ = Task.Run(() => {
        Thread.Sleep(100);
        source.SetResult(42);
    });
    return new ValueTask(source);
}

为什么你不该在业务代码里实现 IValueTaskSource

真正棘手的地方不在接口签名,而在运行时契约:

  • ValueTask 可能被多次 await(只要没调用 GetResult),但你的 IValueTaskSource 实例通常只能完成一次;重复 await 同一个已完成的 ValueTask 会传入旧 token,导致 GetResult 校验失败
  • 没有内置取消支持,要加 CancellationToken 就得自己维护 OperationCanceledException 路径和取消注册逻辑
  • 无法与 async/await 状态机自动集成:你不能在 async 方法里 return new ValueTask(mySource) 并指望编译器帮你生成正确状态机 —— 它只认 TaskValueTask 构造函数中传入的 IValueTaskSource
  • 所有 .NET 内建 API(如 Stream.ReadAsync)返回的 ValueTask 都封装了高度优化、经过压测的 IValueTaskSource 实现(如 ReadValueTaskSource),它们复用缓冲区、跳过调度、内联回调 —— 自己写的几乎不可能比它们更优

除非你在写类似 PipeReader.ReadAsync 这种每秒百万级调用的基础组件,否则直接用 Task.FromResultTask.Delay 或标准 async 方法更安全、更易维护。


# ai  # microsoft  # stream  # c#  # .net  # 为什么  # 封装  # 构造函数  # Token  # int  # 接口  # 线程  # 并发  # 对象  # 异步  # 是一个  # 回调  # 可选  # 高性能  # 它不  # 不可能  # 多个  # 你要  # 你在  # 而在 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel Blade模板引擎语法_Laravel Blade布局继承用法  Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧  Laravel路由怎么定义_Laravel核心路由系统完全入门指南  Python自动化办公教程_ExcelWordPDF批量处理案例  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  如何在香港免费服务器上快速搭建网站?  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  Laravel如何使用Collections进行数据处理?(实用方法示例)  nginx修改上传文件大小限制的方法  Laravel如何使用Telescope进行调试?(安装和使用教程)  高端建站三要素:定制模板、企业官网与响应式设计优化  Laravel DB事务怎么使用_Laravel数据库事务回滚操作  MySQL查询结果复制到新表的方法(更新、插入)  如何撰写建站申请书?关键要点有哪些?  Laravel如何使用集合(Collections)进行数据处理_Laravel Collection常用方法与技巧  php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】  jQuery中的100个技巧汇总  UC浏览器如何设置启动页 UC浏览器启动页设置方法  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  文字头像制作网站推荐软件,醒图能自动配文字吗?  如何破解联通资金短缺导致的基站建设难题?  作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】  微信小程序 require机制详解及实例代码  如何快速生成专业多端适配建站电话?  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  如何用wdcp快速搭建高效网站?  Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】  Python文本处理实践_日志清洗解析【指导】  Laravel如何处理文件下载请求?(Response示例)  Laravel如何从数据库删除数据_Laravel destroy和delete方法区别  Laravel如何处理JSON字段的查询和更新_Laravel JSON列操作与查询技巧  如何快速选择适合个人网站的云服务器配置?  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  免费视频制作网站,更新又快又好的免费电影网站?  Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】  Laravel如何编写单元测试和功能测试?(PHPUnit示例)  详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)  ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】  iOS UIView常见属性方法小结  Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】  如何在IIS7上新建站点并设置安全权限?  深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?  Edge浏览器如何截图和滚动截图_微软Edge网页捕获功能使用教程【技巧】  Laravel怎么定时执行任务_Laravel任务调度器Schedule配置与Cron设置【教程】  php 三元运算符实例详细介绍  Laravel如何处理和验证JSON类型的数据库字段  Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】  佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】  如何快速生成凡客建站的专业级图册?  如何在橙子建站中快速调整背景颜色?