基于C#的ASP.NET Core中分析async、await的使用场景

文章速览

一个赞,留下专属于你的足迹!

一、何时使用async/await

1.核心判断标准

场景 是否使用 async 原因
I/O 操作(数据库、文件、网络请求) ✅ 必须用 释放线程,提高并发
CPU 密集型计算 ❌ 不需要 应该使用 Task.Run 或直接同步
纯内存操作 ❌ 不需要 增加复杂度,无性能收益

2.示例代码

csharp 复制代码
// ✅ 数据库查询 - 需要 async
public async Task<string> GetAllBigClassAsync()
{
    var list = await _context.BigClasses.ToListAsync();  // I/O 操作
    return JsonSerializer.Serialize(list);
}

// ✅ 数据库保存 - 需要 async  
public async Task<string> DeleteNumberDataAsync(int dataId, int userId)
{
    var user = await _context.Users.FindAsync(userId);   // I/O 操作
    // ... 修改数据
    await _context.SaveChangesAsync();                    // I/O 操作
}

二、深度分析:为什么在此类场景中频繁出现?

1.web应用的线程池机制

在ASP.NET Core中,线程池是有限的,大约1000个线程。假设不用async:

csharp 复制代码
// ❌ 同步版本(阻塞线程)
public string GetAllBigClassSync()
{
    var list = _context.BigClasses.ToList(); // 线程被卡住,等待数据库返回
    return JsonSerializer.Serialize(list);
}

出现的问题是:当1000个用户同时请求时,线程池耗尽,第1001个用户必须等待。

使用async后:

  • 发出数据库请求后,当前线程立刻释放,可以处理其他用户请求
  • 数据库返回数据后,从线程池取一个空闲线程继续执行
  • 并发能力提升10-100倍

2.Entity Framework Core的设计

EF Core从底层支持异步,所有的I/O方法都有Async后缀:

csharp 复制代码
// 在你的代码中出现的 EF Core 异步方法:
await _context.BigClasses.ToListAsync();
await _context.NumberRecords.FindAsync(dataId);
await _context.SaveChangesAsync();
await _context.NumberRecords
    .Where(d => d.DataState == 1)
    .CountAsync();
await _context.Database.BeginTransactionAsync();

关键点:数据库查询是网络I/O,不是CPU计算,也正是async的最佳场景。

三、同步vs异步对比分析

1.代码对比

维度 同步方法 异步方法(你的代码)
方法签名 string GetData() async Task<string> GetDataAsync()
数据库查询 .ToList() await .ToListAsync()
线程行为 阻塞线程,干等 释放线程,回调继续
并发能力 低(线程池耗尽) 高(支撑万级并发)
代码复杂度 简单直接 需要 async/await

2.执行流程对比

假设一个请求需要查询数据库(耗时100ms):

同步版本:

时间点: 线程1状态

0ms 开始执行->发送sql->阻塞等待

100ms 收到结果->返回Json

期间线程1被完全占用,无法处理其他请求

异步版本:

时间点: 线程1状态 线程2状态

0ms 开始执行->发送sql->立刻释放 处理其他请求

100ms 空闲 收到结果->继续执行->返回Josn

总结

项目类型 推荐做法 原因
Web API / Razor Pages 全面使用 async I/O 密集,并发要求高
后台定时任务 可部分使用同步 单线程执行,无需高并发
WinForm/WPF async + ConfigureAwait(false) 避免 UI 线程死锁
计算密集型(图像处理、大数据计算) 同步或 Task.Run 不是 I/O,async 无收益
相关推荐
李白的天不白1 小时前
大规模请求数据并发问题
java·前端·数据库
zjy277771 小时前
Golang bcrypt如何加密密码_Golang密码加密教程【收藏】
jvm·数据库·python
万邦科技Lafite1 小时前
API接口一键获取商品评论,根据商品评论分析客户画像
linux·服务器·数据库·windows·microsoft·电商开放平台
phltxy1 小时前
Redis 核心数据类型之 String 详解
数据库·redis·bootstrap
老纪1 小时前
Redis怎样利用Lua为多个Key同步续期
jvm·数据库·python
2403_883261091 小时前
C#怎么计算两个日期的差值_C#如何处理时间跨度【笔记】
jvm·数据库·python
m0_740653221 小时前
Golang切片底层原理是怎样的_Golang切片实现原理教程【简明】
jvm·数据库·python
yexuhgu1 小时前
CSS如何处理CSS逻辑属性兼容性_通过PostCSS转译为物理属性
jvm·数据库·python
m0_624578591 小时前
CSS如何给Bootstrap背景添加半透明层_使用rgba颜色模式与定位
jvm·数据库·python