在 C# 中使用新的 async/await 关键字,现在对您使用 ThreadStatic 数据的方式(以及时间)产生了影响,因为回调委托(delegate)是在与 async
不同的线程上执行的操作开始于。例如,以下简单的控制台应用程序:
[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.SetData
和 CallContext.GetData
并得到相同的行为。
在阅读了一些相关问题和主题之后:
- 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
关键字?
考虑到 async/await 关键字的使用,存储与特定执行线程关联的数据的最佳方式是什么,这些数据可以(自动!)在回调线程上恢复?
谢谢,
最佳答案
您可以使用CallContext.LogicalSetData
和CallContext.LogicalGetData
,但我建议您不要这样做,因为它们不支持任何类型的使用简单并行机制时的“克隆”(Task.WhenAny
/Task.WhenAll
)。
我打开了一个UserVoice request更完整的 async
兼容“上下文”,在 an MSDN forum post 中有更详细的解释.我们自己 build 一个似乎是不可能的。乔恩双向飞碟有一个good blog entry关于这个问题。
因此,我建议您使用参数、lambda 闭包或本地实例的成员 (this
),如 Marc 所述。
是的,OperationContext.Current
不在 await
中保留。
更新:.NET 4.5 在async
代码中支持Logical[Get|Set]Data
。详情 on my blog .
关于c# - 在 async/await 中使用 ThreadStatic 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13010563/