0

0

c# ExecutionContext 和 AsyncLocal 的关系

畫卷琴夢

畫卷琴夢

发布时间:2026-02-27 12:06:02

|

175人浏览过

|

来源于php中文网

原创

asynclocal 是 executioncontext 中槽位的封装,其值依赖 executioncontext 的自动流动,赋值会触发上下文复制,禁用流动或上下文丢失将导致读取 default(t)。

c# executioncontext 和 asynclocal 的关系

ExecutionContext 是 AsyncLocal 的运行时载体

AsyncLocal 本身不存储数据,它只是对 ExecutionContext 中一个“槽位”(slot)的封装。每次读写 AsyncLocal<t>.Value</t>,实际是在当前 ExecutionContext 的上下文中读写其内部维护的一个 Dictionary<asynclocal object></asynclocal> 映射。没有 ExecutionContext 的流转,AsyncLocal 就无法跨异步边界延续值。

默认情况下 ExecutionContext 会自动流动(flow),但可被禁用

当调用 awaitTask.RunThreadPool.QueueUserWorkItem 等操作时,.NET 默认会捕获并传递当前 ExecutionContext(含其中所有 AsyncLocal 值)。但以下情况会中断流动:

  • 显式调用 ExecutionContext.SuppressFlow() 后进入异步分支
  • 使用 Task.Factory.StartNew(..., TaskCreationOptions.DenyChildAttach) 且未传入捕获的上下文
  • 在 ASP.NET Core 2.1+ 中,HttpContext 不再自动绑定到 AsyncLocal,需手动存取(如通过 IHttpContextAccessor

一旦流动被抑制,新任务/线程中的 AsyncLocal.Value 将是默认值(default(T)),而非父上下文的副本。

Natural Language Playlist
Natural Language Playlist

探索语言和音乐之间丰富而复杂的关系,并使用 Transformer 语言模型构建播放列表。

下载

AsyncLocal.Value 的赋值会触发 ExecutionContext 的复制

AsyncLocal<t>.Value</t> 赋值时,如果当前 ExecutionContext 处于“只读”状态(例如刚从线程池回调中恢复),运行时会先 shallow-copy 当前 ExecutionContext,再更新其中该 AsyncLocal 对应的值。这意味着:

  • 频繁赋值可能带来小量分配开销(尤其在高并发异步循环中)
  • 多个 AsyncLocal 实例之间互不影响,各自独立维护 slot
  • 值类型会被装箱存入 ExecutionContext 的对象字典,注意避免意外装箱
var local = new AsyncLocal<int>();
local.Value = 42; // 触发 ExecutionContext 检查与可能的复制
Console.WriteLine(local.Value); // 输出 42

不要依赖 AsyncLocal 在 finalizer 或 unobserved Task 中存活

AsyncLocal 的生命周期严格绑定于 ExecutionContext 的存在周期。而 ExecutionContext 可能在以下场景被提前丢弃:

  • 未 await 的 Task 被 GC 回收(尤其 Task 进入 faulted/canceled 状态后)
  • 使用 ValueChanged 事件注册回调,但回调执行时原上下文已退出(比如 Web 请求结束)
  • async void 方法中修改 AsyncLocal,后续无 await 点,上下文很快失效

这类场景下读取 AsyncLocal.Value 很可能得到 default(T) 或旧值,且无任何异常提示——这是最隐蔽也最难调试的问题之一。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

183

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

125

2025.11.27

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

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

721

2023.08.10

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

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

721

2023.08.10

default gateway怎么配置
default gateway怎么配置

配置default gateway的步骤:1、了解网络环境;2、获取路由器IP地址;3、登录路由器管理界面;4、找到并配置WAN口设置;5、配置默认网关;6、保存设置并退出;7、检查网络连接是否正常。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

233

2023.12.07

Golang 实际项目案例:从需求到上线
Golang 实际项目案例:从需求到上线

《Golang 实际项目案例:从需求到上线》以真实业务场景为主线,完整覆盖需求分析、架构设计、模块拆分、编码实现、性能优化与部署上线全过程,强调工程规范与实践决策,帮助开发者打通从技术实现到系统交付的关键路径,提升独立完成 Go 项目的综合能力。

18

2026.02.26

Golang Web 开发路线:构建高效后端服务
Golang Web 开发路线:构建高效后端服务

《Golang Web 开发路线:构建高效后端服务》围绕 Go 在后端领域的工程实践,系统讲解 Web 框架选型、路由设计、中间件机制、数据库访问与接口规范,结合高并发与可维护性思维,逐步构建稳定、高性能、易扩展的后端服务体系,帮助开发者形成完整的 Go Web 架构能力。

17

2026.02.26

Golang 并发编程专题:掌握多核时代的核心技能
Golang 并发编程专题:掌握多核时代的核心技能

《Golang 并发编程专题:掌握多核时代的核心技能》系统讲解 Go 在并发领域的设计哲学与实践方法,深入剖析 goroutine、channel、调度模型与并发安全机制,结合真实场景与性能思维,帮助开发者构建高吞吐、低延迟、可扩展的并发程序,全面提升多核时代的工程能力。

16

2026.02.26

batoto漫画官网入口与网页版访问指南
batoto漫画官网入口与网页版访问指南

本专题系统整理batoto漫画官方网站最新可用入口,涵盖最新官网地址、网页版登录页面及防走失访问方式说明,帮助用户快速找到batoto漫画官方平台,稳定在线阅读各类漫画内容。

431

2026.02.25

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 10.3万人学习

C 教程
C 教程

共75课时 | 5万人学习

C++教程
C++教程

共115课时 | 19.6万人学习

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

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