使用ThreadStatic变量与异步/等待 [英] using ThreadStatic variables with async/await

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

问题描述

随着新的异步/等待关键字在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 CallContext.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中,所以也许同样的事情与利用发生在这里异步等待关键字?

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 CallContext.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).

我开了一个<一个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 awaits.

更新: .NET 4.5确实支持逻辑[获取|设置]数据异步 code。详情在我的博客

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

这篇关于使用ThreadStatic变量与异步/等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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