AsyncLocal< T>的作用是什么?在非异步/等待代码中? [英] What's the effect of AsyncLocal<T> in non async/await code?

查看:74
本文介绍了AsyncLocal< T>的作用是什么?在非异步/等待代码中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理桌面winform应用程序的非常大的旧代码库.在此代码库中,主要使用BackgroundWorker在后台线程中执行许多操作.

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

我正在尝试更改此设置,并开始使用async/await代码,并受益于在池的任何线程中运行任务,并允许通过使用ConfigureAwait(false)在任何其他线程中继续执行任务.我知道[ThreadStatic]async/await搭配不好,并且我在这里阅读了一些答案,建议改用AsyncLocal<T>.

鉴于我正在使用大型代码库,如前所述,我无法一次性切换到任何地方的async/await,并且我必须逐步进行此更改.因此以前具有[ThreadStatic]的代码将更改为AsyncLocal<T>,但是大部分代码将继续使用BackgroundWorker,并且不会命中任何一行async/await代码.

问题
这会工作吗?我需要能够定义某种上下文流,该上下文流将与我的新async/await代码一起使用,并且还必须继续与依赖于[ThreadStatic]的每一个线程彼此独立的旧非异步代码一起工作.

如果我完全错了,走了错误的道路,建议是很受欢迎的.

解决方案

它应该可以工作.

AsyncLocal<T>是逻辑调用上下文的抽象.我描述了逻辑调用上下文及其与async/的交互方式await 详见旧博客文章.

总的来说,它可能工作正常,但是AsyncLocal<T>的一个方面与ThreadStatic完全不同.

写入AsyncLocal<T>值时,将为当前逻辑调用上下文设置该值. async方法将为其逻辑调用上下文建立写时复制范围,因此,如果在向其写入async方法,则会创建一个 new 包含新值的逻辑调用上下文.这允许async方法以嵌套方式使用它,其中内部"上下文可以覆盖外部"上下文. 但是,内部"上下文值永远不会流回到调用者;恢复外部"上下文后,它将完全替换内部"上下文.

如果所有方法都不是async,并且值仅在其自己的线程中设置,则该线程仅具有单个逻辑调用上下文,并且写入/读取值将与ThreadStatic相同.

I'm working on a very large and old code base of a desktop winform application. In this code base there are lots of operations performed in background threads, mainly using BackgroundWorker.

A common pattern in this code base, is to hide complexity by binding artifacts to the thread being executed. For instance, the database connection and transaction are stored in [ThreadStatic] fields.

I'm trying to change this, and start using async/await code, and benefit from running the task in any thread of the pool, and allowing a task to continue executing in any other thread by using ConfigureAwait(false). I know that [ThreadStatic] doesn't play nice with async/await, and I've read several answers over here suggesting to use AsyncLocal<T> instead.

Given that I'm working on a large code base, as mentioned before, I'm unable to switch to async/await everywhere in a single shot, and I must do this changes gradually. So the code that before had [ThreadStatic] will change to AsyncLocal<T>, but large portions of the code will continue using BackgroundWorker and won't hit a single async/await line of code.

Question
Will this work? I need to be able to define some kind of context flow that will work with my new async/await code, and also keep working with my old non async code which relied on [ThreadStatic] keeping every thread stuff independent from each other.

If I'm totally wrong and going down the wrong path, suggestions are very welcomed.

解决方案

It should work.

AsyncLocal<T> is an abstraction of the logical call context. I describe the logical call context and how it interacts with async/await in detail in an old blog post.

In summary, it will probably work fine, but there is one aspect of AsyncLocal<T> that is quite different than ThreadStatic.

When you write to the AsyncLocal<T> value, that value is set for the current logical call context. An async method will establish a copy-on-write scope for its logical call context, so if you write to it within an async method, it will create a new logical call context that contains the new value. This allows async method to use it in a nested fashion, where "inner" contexts can overwrite "outer" contexts. However, the "inner" context values never flow back to the caller; when the "outer" context is resumed, it completely replaces the "inner" context.

If none of the methods are async and the values are only set from their own threads, then that thread just has a single logical call context, and writing/reading the values will work just the same as ThreadStatic.

这篇关于AsyncLocal&lt; T&gt;的作用是什么?在非异步/等待代码中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆