c# - 在 async/await 中使用 ThreadStatic 变量

标签 c# multithreading synchronization async-await

在 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.SetDataCallContext.GetData 并得到相同的行为。

在阅读了一些相关问题和主题之后:

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

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

谢谢,

最佳答案

可以使用CallContext.LogicalSetDataCallContext.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/

相关文章:

c# - Transient 注入(inject) Singleton 有什么问题?

java - 优雅地中断java线程

c# - 如何在 C# 中为计时器实现任务异步?

multithreading - Redis是单线程的,那它是如何做并发I/O的呢?

c - 使用二进制信号量实现计数信号量

ios - iOS 上 Dropbox sync api 的文件同步问题

java - Java 中的同步 Get 方法

c# - MVVM动态DataGrid排序过滤

c# - VTK r(reset)键代码实现

javascript - 或者 JavaScript 中的声明?