在 async/await 中使用 ThreadStatic 变量 [英] using ThreadStatic variables with async/await

查看:41
本文介绍了在 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:

似乎像 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.Currentawait s 中保留.

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 变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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