AsyncLocal 在非异步/等待代码中的作用是什么?

我正在研究桌面winform应用程序的一个非常大的旧代码库。 在此代码库中,有许多操作在后台线程中执行,主要使用BackgroundWorker

此代码库中的一个常见模式是通过将工件绑定到正在执行的线程来隐藏复杂性。 例如,数据库连接和事务存储在[ThreadStatic]字段中。

我正在尝试更改此设置,并开始使用async/await代码,并从在池的任何线程中运行任务中受益,并允许任务通过使用ConfigureAwait(false)继续在任何其他线程中执行。 我知道[ThreadStatic]async/await不兼容,我在这里读了几个答案,建议使用AsyncLocal

鉴于我正在开发大型代码库,如前所述,我无法一次性切换到async/await ,我必须逐步进行此更改。 因此之前[ThreadStatic]的代码将更改为AsyncLocal ,但代码的大部分将继续使用BackgroundWorker并且不会命中单个async/await代码行。


这会有用吗? 我需要能够定义某种上下文流程,它将与我的新async/await代码一起使用,并且还继续使用依赖于[ThreadStatic]旧的非异步代码,保持每个线程内容彼此独立。

如果我完全错了,走错了路,建议非常受欢迎。

它应该工作。

AsyncLocal是逻辑调用上下文的抽象。 我在旧的博客文章中详细描述了逻辑调用上下文以及它如何与async / await进行交互 。

总之,它可能会正常工作,但AsyncLocal一个方面与ThreadStatic完全不同。

写入AsyncLocal值时,将为当前逻辑调用上下文设置该值。 async方法将为其逻辑调用上下文建立写时复制范围,因此如果 async方法中写入,它将创建包含新值的逻辑调用上下文。 这允许async方法以嵌套方式使用它,其中“内部”上下文可以覆盖“外部”上下文。 但是, “内部”上下文值永远不会回流给调用者; 当“外部”上下文恢复时,它完全取代了“内部”上下文。

如果没有任何方法是async ,并且值只是从它们自己的线程设置,那么该线程只有一个逻辑调用上下文,写入/读取值将与ThreadStatic相同。