【发布时间】:2012-10-12 05:04:39
【问题描述】:
使用 C# 中的新 async/await 关键字,现在会影响您使用 ThreadStatic 数据的方式(和时间),因为回调委托在与 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 关键字的使用,存储与可以(自动!)在回调线程上恢复的特定执行线程关联的数据的最佳方式是什么?
谢谢,
【问题讨论】:
-
AsyncLocal 是现在实现这一目标的现代方式。介意接受我的回答吗?
标签: c# multithreading synchronization async-await