C#中ValueTask

作者:周杰伦fans日期:2025/12/2

在C#中,ValueTask 是一个用于优化异步操作性能的结构体,特别适用于那些可能同步完成的操作。下面我会详细解释它的设计目的、用法和最佳实践。

什么是ValueTask?

ValueTaskTask 类型的轻量级替代品,主要目的是减少异步操作中的内存分配。

1public readonly struct ValueTask : IEquatable<ValueTask>
2{
3    // 结构体实现
4}
5
6public readonly struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>
7{
8    // 泛型版本实现
9}
10

设计动机和解决的问题

Task的内存分配问题

1// 传统Task - 即使同步完成也会分配内存
2public async Task<int> GetDataAsync()
3{
4    if (_cache.TryGetValue(key, out var data))
5    {
6        return data; // 同步完成,但仍然会分配Task
7    }
8    return await FetchFromNetworkAsync();
9}
10

ValueTask的解决方案

1// ValueTask - 同步完成时避免内存分配
2public ValueTask<int> GetDataAsync()
3{
4    if (_cache.TryGetValue(key, out var data))
5    {
6        return new ValueTask<int>(data); // 同步结果,无内存分配
7    }
8    return new ValueTask<int>(FetchFromNetworkAsync()); // 异步操作
9}
10

基本用法

1. 创建ValueTask

1// 同步完成的值
2ValueTask<int> syncTask = new ValueTask<int>(42);
3
4// 从Task转换
5ValueTask<int> fromTask = new ValueTask<int>(Task.FromResult(42));
6
7// 异步操作
8ValueTask<int> asyncTask = new ValueTask<int>(SomeAsyncMethod());
9

2. 使用async/await

1public async ValueTask<int> CalculateAsync(int input)
2{
3    // 检查是否可以同步完成
4    if (input < 0)
5    {
6        return 0; // 同步返回
7    }
8    
9    // 需要异步操作
10    await Task.Delay(100);
11    return input * 2;
12}
13
14// 消费ValueTask
15public async Task ConsumeValueTaskAsync()
16{
17    ValueTask<int> valueTask = CalculateAsync(10);
18    int result = await valueTask;
19    Console.WriteLine(result); // 输出: 20
20}
21

实际应用场景

1. 缓存场景优化

1public class DataService
2{
3    private readonly ConcurrentDictionary<string, string> _cache = new();
4    
5    public ValueTask<string> GetDataAsync(string key)
6    {
7        // 同步检查缓存
8        if (_cache.TryGetValue(key, out var data))
9        {
10            return new ValueTask<string>(data);
11        }
12        
13        // 异步获取数据
14        return new ValueTask<string>(FetchAndCacheDataAsync(key));
15    }
16    
17    private async Task<string> FetchAndCacheDataAsync(string key)
18    {
19        var data = await FetchFromExternalServiceAsync(key);
20        _cache[key] = data;
21        return data;
22    }
23}
24

2. I/O操作优化

1public class StreamReaderOptimized
2{
3    private readonly Stream _stream;
4    private byte[] _buffer;
5    
6    public ValueTask<int> ReadAsync(byte[] buffer, int offset, int count)
7    {
8        // 如果数据已经在缓冲区,同步返回
9        if (_buffer != null && _buffer.Length >= count)
10        {
11            Array.Copy(_buffer, 0, buffer, offset, count);
12            return new ValueTask<int>(count);
13        }
14        
15        // 否则进行异步读取
16        return new ValueTask<int>(_stream.ReadAsync(buffer, offset, count));
17    }
18}
19

3. 池化资源管理

1public class ConnectionPool
2{
3    private readonly ConcurrentQueue<Connection> _pool = new();
4    
5    public ValueTask<Connection> GetConnectionAsync()
6    {
7        // 尝试从池中同步获取
8        if (_pool.TryDequeue(out var connection))
9        {
10            return new ValueTask<Connection>(connection);
11        }
12        
13        // 池为空,异步创建新连接
14        return new ValueTask<Connection>(CreateConnectionAsync());
15    }
16    
17    private async Task<Connection> CreateConnectionAsync()
18    {
19        await Task.Delay(100); // 模拟连接建立
20        return new Connection();
21    }
22}
23

高级用法和模式

1. 手动实现ValueTask源

1public class ValueTaskCompletionSource<T>
2{
3    private ManualResetValueTaskSourceCore<T> _core;
4    
5    public ValueTask<T> Task => new ValueTask<T>(this, _core.Version);
6    
7    public void SetResult(T result)
8    {
9        _core.SetResult(result);
10    }
11    
12    public void SetException(Exception exception)
13    {
14        _core.SetException(exception);
15    }
16    
17    // 实现必要的接口方法
18    public short Version => _core.Version;
19    public void SetCompleted() => _core.SetCompleted();
20    public T GetResult(short token) => _core.GetResult(token);
21    public ValueTaskSourceStatus GetStatus(short token) => _core.GetStatus(token);
22    public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
23        => _core.OnCompleted(continuation, state, token, flags);
24}
25

2. 使用IValueTaskSource

1public class CustomAsyncOperation<T> : IValueTaskSource<T>
2{
3    private ManualResetValueTaskSourceCore<T> _core;
4    
5    public ValueTask<T> RunAsync()
6    {
7        // 启动异步操作
8        StartOperation();
9        return new ValueTask<T>(this, _core.Version);
10    }
11    
12    private async void StartOperation()
13    {
14        try
15        {
16            T result = await PerformWorkAsync();
17            _core.SetResult(result);
18        }
19        catch (Exception ex)
20        {
21            _core.SetException(ex);
22        }
23    }
24    
25    // 实现IValueTaskSource接口
26    public T GetResult(short token) => _core.GetResult(token);
27    public ValueTaskSourceStatus GetStatus(short token) => _core.GetStatus(token);
28    public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
29        => _core.OnCompleted(continuation, state, token, flags);
30}
31

性能对比

基准测试示例

1[MemoryDiagnoser]
2public class TaskVsValueTaskBenchmark
3{
4    private readonly Random _random = new Random();
5    
6    [Benchmark]
7    public async Task<int> TraditionalTask()
8    {
9        return await GetDataTaskAsync();
10    }
11    
12    [Benchmark]
13    public async Task<int> ValueTaskOptimized()
14    {
15        return await GetDataValueTaskAsync();
16    }
17    
18    private async Task<int> GetDataTaskAsync()
19    {
20        if (_random.Next(2) == 0)
21            return 42; // 50%几率同步完成
22            
23        await Task.Delay(1);
24        return 100;
25    }
26    
27    private ValueTask<int> GetDataValueTaskAsync()
28    {
29        if (_random.Next(2) == 0)
30            return new ValueTask<int>(42); // 无内存分配
31            
32        return new ValueTask<int>(GetAsyncData());
33        
34        async Task<int> GetAsyncData()
35        {
36            await Task.Delay(1);
37            return 100;
38        }
39    }
40}
41

使用准则和最佳实践

应该使用ValueTask的情况

  1. 高频调用的异步方法
  2. 可能同步完成的操作
  3. 性能敏感的热路径
  4. 内存受限的环境

应该避免使用ValueTask的情况

  1. 长期存在的异步操作
  2. 需要多次await的操作
  3. 在UI线程中可能阻塞的操作

重要注意事项

1//  错误:多次await ValueTask
2ValueTask<int> task = GetDataAsync();
3int result1 = await task;
4// int result2 = await task; // 错误!ValueTask只能await一次
5
6//  正确:转换为Task如果需要多次使用
7Task<int> task = GetDataAsync().AsTask();
8int result1 = await task;
9int result2 = await task; // 可以,但通常不是好设计
10
11//  正确:使用ConfigureAwait
12int result = await GetDataAsync().ConfigureAwait(false);
13

与Task的互操作

1// ValueTask  Task
2ValueTask<int> valueTask = GetDataAsync();
3Task<int> task = valueTask.AsTask();
4
5// Task  ValueTask
6Task<int> originalTask = Task.FromResult(42);
7ValueTask<int> valueTask = new ValueTask<int>(originalTask);
8
9// 在接口中使用
10public interface IDataProvider
11{
12    ValueTask<Data> GetDataAsync();
13}
14
15public class DataService : IDataProvider
16{
17    public async ValueTask<Data> GetDataAsync()
18    {
19        // 实现
20    }
21}
22

总结

ValueTask 是C#中重要的性能优化工具,它:

  • 减少内存分配:特别适合可能同步完成的异步操作
  • 提高性能:在高频调用场景下显著提升性能
  • 保持兼容性:可以与Task无缝互操作
  • 需要谨慎使用:遵循一次await的原则

正确使用 ValueTask 可以在不改变代码逻辑的前提下,为应用程序带来显著的性能提升。


C#中ValueTask》 是转载文章,点击查看原文


相关推荐


为什么C语言拒绝函数重载?非要重载怎么做?
码事漫谈2025/11/30

在我们学习C++、Java或C#时,函数重载(Function Overloading)是一个再自然不过的概念:允许两个或多个函数使用相同的名字,只要它们的参数列表(参数的类型、个数或顺序)不同即可。编译器会根据调用时传入的实参,自动选择最匹配的那个函数。 然而,当我们回到C语言的世界,这条规则却失效了。如果你定义了两个同名的函数,即使参数列表不同,编译器也会毫不留情地报出一个“重定义”错误。 那么,为什么C语言的设计者,要“剥夺”这个看似非常实用的特性呢? 答案并非“不能”,而是“不为”。这背


Flask项目:从零到一搭建一个精美的“每天十句话“网页系统
数据知道2025/11/27

更多内容请见: Python Web项目集锦-专栏介绍和目录 文章目录 前言 一、环境准备 1.1 项目结构 1.2 依赖安装 1.3 配置数据库 二、完整代码 2.1 main.py (Flask后端) 2.2 templates/index.html (前端界面) 2.3


不愧是国内首个视觉编程模型,一张草稿图直接做了一个电子版City Walk
LucianaiB2025/11/24

“City Walk”太费腿?那就让AI替你走一遍。 本文记录我如何用 Doubao-Seed-Code —— 国内首个具备原生视觉理解能力的AI编程模型,把一张手绘草图变成一个可交互的“电子城市漫步”应用。全程零代码基础,仅靠对话完成编程。 一.背景 “City Walk”——城市漫步,曾是年轻人逃离内卷的诗意解药:绿灯直行、红灯拐弯、路口掷骰子、遇见小店就进去坐坐,拍一百张照片,只为记录一条无人知晓的小巷。它不为打卡,只为“瞎溜达”。 但对我这种能坐绝不站、能躺绝不坐的懒人来说: “走1


~/.ssh/config 作用详解
哈里谢顿2025/11/23

这是一个非常好的问题!我们来深入解释 ~/.ssh/config 的作用,以及你写的这段配置为什么能让 ssh devstack-vm 一键完成复杂连接。 📁 一、~/.ssh/config 是什么? ~/.ssh/config 是 OpenSSH 客户端的用户级配置文件,用于为不同的 SSH 连接定义别名、主机地址、用户名、密钥、代理跳转、端口转发等参数。 ✅ 它的作用类似于“SSH 连接的快捷方式 + 自动化脚本”。 当你执行: ssh some-host SSH 客户端会: 查


【底层机制】Android图形渲染体系深度解析:VSync信号机制
沐怡旸2025/11/21

在Android图形渲染体系中,VSync(Vertical Synchronization,垂直同步)是贯穿CPU、GPU与显示器协同工作的核心机制。它不仅解决了画面撕裂、卡顿等关键问题,更定义了Android渲染的"时间节拍"。本文将从底层原理、Android实现架构、关键细节到开发实践,系统拆解VSync信号机制的核心逻辑。 一、核心定义:什么是VSync信号? VSync信号本质是显示器硬件产生的周期性同步信号,其周期与显示器刷新率强相关(例如60Hz刷新率对应16.67ms/帧,90


黑马程序员苍穹外卖(新手) DAY3
烤麻辣烫2025/11/19

公共字段自动填充 问题:代码冗余,不便于后期维护 自定义注解AutoFill,用于标识需要需要进行公共字段填充的方法 自定义切面AutoFillAspect,统一拦截加入了AutoFill注解的方法, 通过反射为公共字段赋值 在Mapper的方法上加入AutoFill注解 serviceImpl 技术点:枚举,注解,AOP,反射 新增菜品 文件上传 yml dev-yml OssConfiguration Co


如何用Claude Code构建公司:三家YC初创公司的案例研究
是魔丸啊2025/11/18

转载 日期:2025年11月17日 阅读时间:5分钟 Y Combinator是一家创业加速器,自2005年以来已经孵化了超过5000家公司,这些公司的总估值超过8000亿美元,包括Airbnb、Stripe和DoorDash等知名企业。 如今,像Claude Code这样的agent编码工具正在从根本上改变YC初创公司构建和扩展的方式。创始人现在可以直接从终端发布产品,将开发周期从几周压缩到几小时,甚至让非技术创始人从第一天起就能与成熟企业竞争。 我们采访了三家展示这一变革实践的YC初创公司:


Python 的内置函数 staticmethod
IMPYLH2025/11/17

Python 内建函数列表 > Python 的内置函数 staticmethod Python 的内置函数 staticmethod 用于将一个方法转换为静态方法。静态方法不需要隐式地传递任何参数(如 self 或 cls),它们与普通函数类似,但属于类的命名空间。 使用方法 定义静态方法:在类中使用 @staticmethod 装饰器来定义静态方法。 class MyClass: @staticmethod def static_method(arg1, arg2):


ArrayUtils:Java数组操作的瑞士军刀
白衣鸽子2025/11/16

1. 前言 本文介绍的 ArrayUtils 以org.apache.commons.collections4.ArrayUtils 为例 源代码:org.apache.commons.collections4.ArrayUtils 自定义特征可以在自己服务内实现 在Java应用开发中,数组操作是我们日常编码的基础任务之一。你是否曾写过下面这样的代码? public boolean findUser(String[] users, String targetUser) { if (u


一文搞懂 AI 流式响应
只想写个小玩意2025/11/15

这是 OpenAI 文档中流式响应的代码 platform.openai.com/docs/guides… import { OpenAI } from "openai"; const client = new OpenAI(); const stream = await client.responses.create({ model: "gpt-5", input: [ { role: "user", conte

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读