使用ThreadStatic变量与异步/等待 [英] using ThreadStatic variables with async/await
问题描述
随着新的异步/等待关键字在C#中,现在有冲击的方式(何时)使用ThreadStatic数据,因为回调委托在不同的线程中执行一个在异步
操作开始。举例来说,下面这个简单的控制台应用程序:
With the new async/await keywords in C#, there are now impacts to the way (and when) you use ThreadStatic data, because the callback delegate is executed on a different thread to one the async
operation started on. For instance, the following simple Console app:
[ThreadStatic]
private static string Secret;
static void Main(string[] args)
{
Start().Wait();
Console.ReadKey();
}
private static async Task Start()
{
Secret = "moo moo";
Console.WriteLine("Started on thread [{0}]", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Secret is [{0}]", Secret);
await Sleepy();
Console.WriteLine("Finished on thread [{0}]", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Secret is [{0}]", Secret);
}
private static async Task Sleepy()
{
Console.WriteLine("Was on thread [{0}]", Thread.CurrentThread.ManagedThreadId);
await Task.Delay(1000);
Console.WriteLine("Now on thread [{0}]", Thread.CurrentThread.ManagedThreadId);
}
将输出的东西沿着线:
will output something along the line of:
Started on thread [9]
Secret is [moo moo]
Was on thread [9]
Now on thread [11]
Finished on thread [11]
Secret is []
我也尝试使用 CallContext.SetData code>和
CallContext.GetData code>并得到了相同的行为。
I've also experimented with using CallContext.SetData
and CallContext.GetData
and got the same behaviour.
阅读一些相关的问题和线程后:
After reading some related questions and threads:
- CallContext中VS ThreadStatic
- http://forum.springframework.net/showthread.php?572-CallContext-vs-ThreadStatic-vs-HttpContext&highlight=LogicalThreadContext
- http://piers7.blogspot.co.uk/2005/11/threadstatic-callcontext-and_02.html
- CallContext vs ThreadStatic
- http://forum.springframework.net/showthread.php?572-CallContext-vs-ThreadStatic-vs-HttpContext&highlight=LogicalThreadContext
- http://piers7.blogspot.co.uk/2005/11/threadstatic-callcontext-and_02.html
似乎像ASP.Net框架明确地迁移跨线程HttpContext的,而不是 CallContext中
,所以也许同样的事情与利用发生在这里异步
和等待
关键字?
it seems that frameworks like ASP.Net explicitly migrates the HttpContext across threads, but not the CallContext
, so perhaps the same thing is happening here with the use of async
and await
keywords?
通过使用异步电动机/等候心中的关键字,什么是存储回调线程上恢复了与特定执行线程可以(自动!)相关的数据的最佳方式?
With the use of the async/await keywords in mind, what's the best way to store data associated with a particular thread of execution that can be (automatically!) restored on the callback thread?
谢谢,
推荐答案
您的可能的使用 CallContext.LogicalSetData code>和
CallContext.LogicalGetData code>,但我建议你不要因为他们不支持任何形式的克隆,当您使用简单的并行度(
Task.WhenAny
/ Task.WhenAll
)。
You could use CallContext.LogicalSetData
and CallContext.LogicalGetData
, but I recommend you don't because they don't support any kind of "cloning" when you use simple parallelism (Task.WhenAny
/ Task.WhenAll
).
我开了一个<一个href=\"http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2698599-add-an-async-compatible-logical-call-context-\">UserVoice申请更完整异步
兼容的背景,更详细的<一个解释href=\"http://social.msdn.microsoft.com/Forums/en-US/async/thread/ea21ca57-5340-439c-8ee9-f0185b5787a1#a6d5ce0e-53bb-47e3-a3ee-d84d6f062dcb\">an MSDN论坛帖子。这似乎并不可能去建筑一个自己。乔恩斯基特有一个<一个href=\"http://$c$cblog.jonskeet.uk/2010/11/08/the-importance-of-context-and-a-question-of-explicitness/\">good关于这个问题的博客条目。
I opened a UserVoice request for a more complete async
-compatible "context", explained in more detail in an MSDN forum post. It does not seem possible to build one ourselves. Jon Skeet has a good blog entry on the subject.
所以,我推荐你使用的说法,拉姆达关闭,或本地实例成员(这个
),如马克描述。
So, I recommend you use argument, lambda closures, or the members of the local instance (this
), as Marc described.
是的, OperationContext.Current
是的不的$ P $横渡 pserved等待
秒。
And yes, OperationContext.Current
is not preserved across await
s.
更新: .NET 4.5确实支持逻辑[获取|设置]数据
在异步
code。详情在我的博客。
Update: .NET 4.5 does support Logical[Get|Set]Data
in async
code. Details on my blog.
这篇关于使用ThreadStatic变量与异步/等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!