C# 中使用ValueTask优化异步方法
概要
我们在开发过程中,经常使用async的异步方法,但是有些时候,异步的方法中,可能包含一些同步的处理。本文主要介绍通过ValueTask这个struct,优化异步处理的方法性能。
代码及实现
有些时候我们会缓存一些数据在内存中,这些数据因为不经常改变,所以并不需要每次都要从后台数据库中获取。
例如下面的代码:
private static List<Branch> _branches;public async Task<List<Branch>> getBranches(){if (_branches is null){using (var context = new BankContext()){_branches = await context.Branches.ToListAsync();} }return _branches;
}
在一个银行App相关的系统中,我们将分行的基本信息缓存在内存中,方便其它方法调用。
上面的代码有一个问题,无论我们的缓存是否命中,都会以Task<List>的形式返回。也就是说Runtime需要为返回Task相关的内容分配内存空间;如果缓存命中,意味着该方法仅仅是执行同步操作,实际上只是一个同步操作。
如果以Task<List>作为返回值,对于同步操作而言,完全是在浪费系统资源。Task是一个类,这就意味着只要我们要使用该类,就必须创建对象,然后在通过GC收集。
对于一些高吞吐量,高并发的站点,如果可以对其进行适当优化,可以节约大量资源。
ValueTask 解决方法
在.Net Core .2.0中,引入一个结构体类型 ValueTask, 用于处理async方法中,同步和异步返回并存的情况。
因为其只是一个结构体,它并不需要像Task那样去创建对象,再被GC收集。但是它却可以包裹TResult或Task,作为async方法的返回值。
我们将上面的代码进行修改,将Task替换成ValueTask即可
private static List<Branch> _branches;
public async ValueTask<List<Branch>> getBranchesByTaskValue(){if (_branches is null){using (var context = new BankContext()){_branches = await context.Branches.ToListAsync();return _branches;} }return _branches;
}
我们用Benchmark测试上述两个方法的性能。

从测试结果上看,ValueTask作为返回值,消耗时间增加了约27%,但是内存消耗几乎可以忽略不计。
全部代码请参考附录
附录
Programs.cs
using System.Diagnostics;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Net.Mail;
using System.ComponentModel.Design.Serialization;
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Collections.Generic;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
namespace IQueryableIEnumerable
{[MemoryDiagnoser]public class Programs{[Benchmark]public async Task getBranches(){TaskValueTest task = new TaskValueTest();for(var i=0;i<5;++i){await task.getBranches();}}[Benchmark]public async Task getBranchesByValueTask(){TaskValueTest task = new TaskValueTest();for(var i=0;i<5;++i){await task.getBranchesByTaskValue();}}public static void Main(string[] args){var summary = BenchmarkRunner.Run<Programs>(); } }
}
TaskValueTest.cs
namespace IQueryableIEnumerable
{using System;using System.Threading;using System.Threading.Tasks;using Microsoft.EntityFrameworkCore;using System.Linq;using System.Collections.Generic;using BenchmarkDotNet.Running;using BenchmarkDotNet.Attributes;using BenchmarkDotNet.Diagnosers;public class TaskValueTest{private static List<Branch> _branches;private static List<Branch> _branches2;public async ValueTask<List<Branch>> getBranchesByTaskValue(){if (_branches is null){using (var context = new BankContext()){_branches = await context.Branches.ToListAsync();} }return _branches;}public async Task<List<Branch>> getBranches(){if (_branches2 is null){using (var context = new BankContext()){_branches2 = await context.Branches.ToListAsync();} }return _branches2;}}
}
相关文章:
C# 中使用ValueTask优化异步方法
概要 我们在开发过程中,经常使用async的异步方法,但是有些时候,异步的方法中,可能包含一些同步的处理。本文主要介绍通过ValueTask这个struct,优化异步处理的方法性能。 代码及实现 有些时候我们会缓存一些数据在内…...
KVM创建新的虚拟机(图形化)
1.启动kvm管理器 [rootlocalhost ~]# virt-manager2.点击创建虚拟机 3.选择所需os安装镜像 4.选择合适的内存大小和CPU 5.创建所需磁盘 6.命名创建的虚拟机...
正则表达式在格式校验中的应用以及包装类的重要性
文章目录 正则表达式:做格式校验包装类:在基本数据类型与引用数据类型间的桥梁总结 在现代IT技术岗位的面试中,掌握正则表达式的应用以及理解包装类的重要性是非常有益的。这篇博客将围绕这两个主题展开,帮助读者更好地面对面试挑…...
Docker使用之java项目工程的部署
同样本文的基础建立在已在目标服务器(以linux为示例)上安装了docker,安装教程请移步度娘 若容器存在请先停止,在删除,然后删除镜像重新编译 //停止容器 sudo docker stop datatransfer//删除容器 sudo docker rm dat…...
3ds Max如何进行合成的反射光泽通道渲染
推荐: NSDT场景编辑器 助你快速搭建可二次开发的3D应用场景 1. 准备场景 步骤 1 打开 3ds Max。smart_phone.max打开已 随教程提供。 打开 3ds Max 步骤 2 按 M 打开材质编辑器。选择空材料 槽。单击漫射通道。它将打开材质/贴图浏览器窗口。选择位图࿰…...
114、Spring AOP是如何实现的?它和AspectJ有什么区别?
Spring AOP是如何实现的?它和AspectJ有什么区别? 一、AOP的理解1、spring aop:动态代理实现2、spring aop 和 AspectJ的区别3、小图一、AOP的理解 其实,AOP只是一种编程思想,表示面向切面编程,如果想实现这种思想,可以使用动态代理啊,第三方的框架 AspectJ啊等等。 1…...
正则表达式速通
简介 正则表达式,我们可以看作通配符的增强版,可以帮我们匹配指定规则的字符串,在计算机中应用广泛,比如说爬虫、网站的登录表单等。 原视频:https://www.bilibili.com/video/BV1da4y1p7iZ 学习正则表达式的常用工具…...
数据可视化(5)热力图及箱型图
1.热力图 #基本热力图 #imshow(x) #x,数据 x[[1,2],[3,4],[5,6],[7,8],[9,10]] plt.imshow(x) plt.show() #使用热力图分析学生的成绩 dfpd.read_excel(学生成绩表.xlsx) #:表示行号 截取数学到英语的列数 xdf.loc[:,"数学":英语].…...
React 组件通信-全面解析
父子组件通信 // 导入 import { useState } from "react";import "./App.scss"; import { defaultTodos } from "./components/module/contentData";// 子组件 const Module ({ id, done, text, onToggle, onDelData }) > {return (<div…...
“深入理解Spring Boot:快速构建微服务架构的利器“
标题:深入理解Spring Boot:快速构建微服务架构的利器 摘要:Spring Boot是一种基于Spring框架的开源项目,它通过自动化配置和约定优于配置的原则,使得开发者能够快速构建微服务架构。本文将深入介绍Spring Boot的特点和…...
SpringBoot超级详解
1.父工程的父工程 在父工程的父工程中的核心依赖,专门用来版本管理的 版本管理。 2.父工程 资源过滤问题,都帮解决了,什么配置文件,都已经配置好了,资源过滤问题是帮助,过滤解决让静态资源文件能够过滤到…...
手机的python怎么运行文件,python在手机上怎么运行
大家好,小编来为大家解答以下问题,手机上的python怎么运行程序,手机的python怎么运行文件,今天让我们一起来看看吧! 1、python程序怎么在手机上运行 python语言应用很广泛,自己也很喜欢使用它,其…...
RBAC三级树状菜单实现(从前端到后端)未完待续
1、表格设计 RBAC 2、前端路由 根据不同的用户id显示不同的菜单。 根据路由 3、多级菜单 展示所有权限,并且根据当前用户id展示它所属的角色的所有菜单。 前端树状展示 思路: 后端:传给前端map,map里1个是所有菜单&am…...
牛客网Verilog刷题——VL41
牛客网Verilog刷题——VL41 题目答案 题目 请设计一个可以实现任意小数分频的时钟分频器,比如说8.7分频的时钟信号,注意rst为低电平复位。提示:其实本质上是一个简单的数学问题,即如何使用最小公倍数得到时钟周期的分别频比。设小…...
大整数截取解决方法(java代码)
大整数截取解决方法(java代码) 描述输入描述输出描述输入示例输出示例前置知识:代码 解题思路来自这个博客:简单^不简单 https://blog.csdn.net/younger_china/article/details/126376374 描述 花花有一个很珍贵的数字串…...
Spring Boot使用@Async实现异步调用:自定义线程池
一、定义线程池 第一步,先在Spring Boot主类中定义一个线程池,比如: SpringBootApplication public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}EnableAsyncConfigurat…...
GFS 分布式文件系统
目录 一、GlusterFS 概述 1.2.GlusterFS特点 1.3.GlusterFS 术语 1.4GlusterFS 的工作流程 二、GlusterFS的卷类型 2.1分布式卷(Distribute volume) 2.1.1特点 2.2条带卷(Stripe volume) 2.2.1条…...
PHP-mysql学习笔记
如题 记录发送emoji数据无法正常显示的问题PHPMysql 记录 发送emoji数据无法正常显示的问题 问题描述 前端发送关于emoji的表情数据给php,php写入mysql php接收到了数据,但无法写入写入过后返回前端无法正常显示 PHP 在对应的pdd函数中设置字符集为utf8mb4 Mysql emoji数…...
AI技术快讯:清华开源ChatGLM2双语对话语言模型
ChatGLM2-6B是一个开源项目,提供了ChatGLM2-6B模型的代码和资源。根据提供的搜索结果,以下是对该项目的介绍: 论文:https://arxiv.org/pdf/2103.10360.pdf ChatGLM2-6B是一个开源的双语对话语言模型,是ChatGLM-6B模…...
网络基础知识
1、什么是链接? 链接是指两个设备之间的连接。它包括用于一个设备能够与另一个设备通信的电缆类型和协议。 2、OSI 参考模型的层次是什么? 有 7 个 OSI 层:物理层,数据链路层,网络层,传输层,会话层,表…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
