C#异步编程async/await
总结
async/await使C#用以实现协程编程的方式,由Task调度器统一调度每一个异步任务的执行,从调度器的线程池中拿出线程来执行,遇到await时线程会被回收,直到异步方法执行完成
async本身没有任何实际作用,只是在编码期给程序员提示调用的方法为异步,真正起作用的是await和Task实例,await遇到Task实例便会将当前线程异步等待,直到执行Task实例的线程结束
主线程执行到await后便停止,不再继续执行后续代码,直到辅线程执行完await发起的异步任务
同时发起多个异步任务
把Task实例保存在一个数组中,用await Task.WhenAll(taskArray)
等待所有异步任务结束,不可每个任务单独使用一个await
参考:
- https://stackoverflow.com/questions/25009437/running-multiple-async-tasks-and-waiting-for-them-all-to-complete
- https://stackoverflow.com/questions/12337671/using-async-await-for-multiple-tasks
自定义异步方法
方法标记为async,用await发起一个Task实例,在Task实例中定义要异步执行的任务
创建Task实例的简便方式是用Task.Run
静态方法,入参是任务的lambda表达式
private async Task<string> SetSysBatchId(string traceCode)
{
return await Task.Run(() =>
{
return SecurityHelper.md5(traceCode);
});
}
网上资源摘要
链接:
如果没有使用await关键字,那么该方法就作为一个同步方法。编译器将向我们显示警告,但不会显示任何错误。
async/await本质上只是一个语法糖,它并不产生线程,只是在编译时把语句的执行逻辑改了,相当于过去我们用callback,这里编译器帮你做了
async并不是表明这个方法是异步方法,而是表明这个方法里有异步调用,真正重要的是await,他会同步等待异步调用的完成
async 和 await 关键字不会创建其他线程。因为异步方法不会在其自身线程上运行,因此它不需要多线程。
如果使用 async 修饰符将某种方法指定为异步方法,即启用以下两种功能。
- 标记的异步方法可以使用 await 来指定暂停点。 await 运算符通知编译器异步方法:在等待的异步过程完成后才能继续通过该点。 同时,控制返回至异步方法的调用方。
- 异步方法在 await 表达式执行时暂停并不构成方法退出,只会导致 finally 代码块不运行。
标记的异步方法本身可以通过调用它的方法等待。
如果异步方法未使用 await 运算符标记暂停点,则该方法会作为同步方法执行,即使有 async 修饰符,也不例外。
I/O 绑定和CPU 绑定的不同编程方式:
- 如果工作为 I/O 绑定,使用 async 和 await(而不使用 Task.Run)。 不应使用任务并行库。
- 如果工作属于 CPU 绑定,并且重视响应能力,使用 async 和 await,但在另一个线程上使用 Task.Run 生成工作。 如果同时适用于并发和并行,应考虑使用任务并行库。
类似于线程池工作项对异步操作的封装,任务是对异步操作的另一种形式的封装
任务启动后,通过任务调度器TaskScheduler来调度。.NET中提供两种任务调度器,一种是线程池任务调度器,也是默认调度器,它会将任务派发给线程池工作者线程;另一种是上下文同步任务调度器,它会将任务派发给当前上下文线程
async 方法被编译成一个状态机,结合task调度系统,实现语言运行时的协程
csharp语言内部实现了task的调度器,通过线程池来执行task,当一个task wait的时候,就 让出线程,调度别的task在 线程上执行
await/async和线程没有具体的关系,只是编译器的语法糖,用于在编译时是否转换为状态机,成为协程(协程也叫纤程),将await变成一个stackless协程由状态机实现
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通