27

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.

4

1 回答 1

41

它应该工作。

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

总而言之,它可能会正常工作,但有一个方面AsyncLocal<T>ThreadStatic.

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

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

于 2017-03-22T18:22:06.500 回答