0

0

c# 高并发下 async 方法中的 try-finally 模式

星降

星降

发布时间:2026-01-20 12:40:04

|

489人浏览过

|

来源于php中文网

原创

能,async方法中try-finally的finally块总会执行,前提是await任务最终完成(成功、失败或取消),且方法未被线程中止;编译器将其转为状态机,清理逻辑注册为Task完成时的延续。

c# 高并发下 async 方法中的 try-finally 模式

async 方法里 try-finally 能否保证 finally 执行?

能,但前提是 await 的任务最终完成(无论成功、失败或被取消)。只要 await 表达式所在的 async 方法没有被线程中止(这在 .NET 中几乎不可能发生),finally 块一定会执行——哪怕 await 后抛出异常、或任务被 CancellationToken 取消触发 OperationCanceledException

常见误解是“await 会跳出方法,finally 就不走了”,其实编译器把 async 方法重写为状态机,try-finally 被拆解为状态迁移逻辑,finally 对应的清理代码会被注册为延续(continuation),由 Task 完成时调度执行。

高并发下 finally 块可能被延迟执行吗?

不会延迟执行逻辑本身,但执行时机受 TaskScheduler 和同步上下文影响。在 ASP.NET Core 默认无同步上下文环境下,finally 通常在 ThreadPool 线程上立即回调;若在 WinForms/WPF 中使用 await 且未加 .ConfigureAwait(false)finally 会排队到 UI 线程,可能因消息队列积压而感知到延迟。

  • 高并发本身不导致 finally 延迟,但大量未完成的 Task 会增加调度开销
  • finally 里做了同步 I/O(如 File.WriteAllText)或长时间 CPU 计算,会阻塞当前线程,影响吞吐
  • 不要在 finallyawait —— 编译器会报错:CS4032: 'await' cannot be used in a 'finally' clause

资源释放场景:IDisposable 对象在 async 方法中怎么安全处置?

IDisposable 实例不能靠 using(它只支持同步 dispose),必须显式在 finally 中调用 Dispose()。若对象本身支持异步释放(如 IAsyncDisposable),则需另作处理——finally 无法 await,所以不能直接调用 DisposeAsync()

典型做法是:对纯同步资源(如 MemoryStream、自定义锁对象)用 try-finally + Dispose();对真正需要异步释放的资源(如数据库连接池中的连接),应避免在 finally 中处理,改用 await using(C# 8+)并确保整个方法是 async

public async Task ProcessDataAsync()
{
    await using var conn = new SqlConnection(_connStr);
    await conn.OpenAsync();
    // ... do work
} // DisposeAsync() 在此处自动 await

如果必须混合同步/异步资源,建议拆分逻辑:同步资源用 try-finally,异步资源用 await using 或手动 try-catch-await 处理 DisposeAsync()

启科网络PHP商城系统
启科网络PHP商城系统

启科网络商城系统由启科网络技术开发团队完全自主开发,使用国内最流行高效的PHP程序语言,并用小巧的MySql作为数据库服务器,并且使用Smarty引擎来分离网站程序与前端设计代码,让建立的网站可以自由制作个性化的页面。 系统使用标签作为数据调用格式,网站前台开发人员只要简单学习系统标签功能和使用方法,将标签设置在制作的HTML模板中进行对网站数据、内容、信息等的调用,即可建设出美观、个性的网站。

下载

容易踩的坑:Cancellation 和 finally 的交互

await 的任务因取消而抛出 OperationCanceledExceptionfinally 仍会执行——这是正确行为。但开发者常误以为“取消 = 跳过清理”,结果导致资源泄漏。

另一个陷阱是:在 catch 中重新抛出异常后,finally 仍执行;但如果在 catch 中调用了 Environment.FailFast() 或触发了堆溢出等不可恢复错误,finally 就不会运行——不过这种场景在高并发服务中极少见,也不该主动引入。

关键检查点:

  • 确认所有 await 调用都传入了同一 CancellationToken,避免部分操作未响应取消导致 finally 长时间挂起
  • 不要在 finally 中 throw 新异常——它会覆盖原始异常,掩盖根因
  • finally 中调用的方法可能抛异常(如 stream.Dispose() 在网络流已断开时),应额外包一层 try-catch 并记录日志,防止压制上游错误

高并发下最易被忽略的是:finally 里的代码不是“原子”的——它可能被其他并发请求的相同逻辑交叉执行,所以涉及共享状态(如静态计数器、日志缓冲区)时,必须加锁或用线程安全类型(如 InterlockedConcurrentQueue)。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

392

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

392

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

481

2023.08.10

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

352

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2075

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

347

2023.08.31

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

13

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号