使用带有 async/await 的 ThreadStatic 变量

using ThreadStatic variables with async/await(使用带有 async/await 的 ThreadStatic 变量)

本文介绍了使用带有 async/await 的 ThreadStatic 变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 C# 中的新 async/await 关键字,现在会影响您使用 ThreadStatic 数据的方式(和时间),因为回调委托在与 async 不同的线程上执行操作开始.例如,以下简单的控制台应用程序:

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);
}

将输出如下内容:

Started on thread [9]
Secret is [moo moo]
Was on thread [9]
Now on thread [11]
Finished on thread [11]
Secret is []

我也尝试过使用 CallContext.SetDataCallContext.GetData 并得到相同的行为.

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

似乎像 ASP.Net 这样的框架显式地跨线程迁移 HttpContext,而不是 CallContext,因此使用 async 可能会发生同样的事情和 await 关键字?

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?

考虑到 async/await 关键字的使用,存储与可以(自动!)在回调线程上恢复的特定执行线程关联的数据的最佳方式是什么?

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.LogicalSetDataCallContext.LogicalGetData,但是我建议您不要这样做,因为当您使用简单的并行性 (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).

我打开了一个 UserVoice请求获得更完整的 async 兼容上下文",在 一篇 MSDN 论坛帖子.似乎不可能自己建造一个.Jon Skeet 有一个不错的博客条目 关于这个主题.

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.

因此,我建议您使用参数、lambda 闭包或本地实例的成员 (this),如 Marc 所述.

So, I recommend you use argument, lambda closures, or the members of the local instance (this), as Marc described.

是的,OperationContext.Current 没有awaits 中保留.

And yes, OperationContext.Current is not preserved across awaits.

更新: .NET 4.5 确实支持 async 代码中的 Logical[Get|Set]Data.详情在我的博客上.

Update: .NET 4.5 does support Logical[Get|Set]Data in async code. Details on my blog.

这篇关于使用带有 async/await 的 ThreadStatic 变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:使用带有 async/await 的 ThreadStatic 变量

基础教程推荐