C#/ .Net使用ThreadLocal和Async / Await

时间:2018-02-25 12:48:15

标签: c# .net async-await

让我们想象一下这样的代码:

private static readonly ThreadLocal<int> MyInt = new ThreadLocal<int>(() => 3);

DoSomething()
{
    var A = DoSomethingElse()
    MyInt += A;
}

因此,每个帖子都会有MyInt的副本。

但如果我们做了类似的事情:

private static readonly ThreadLocal<int> MyInt = new ThreadLocal<int>(() => 3);

async DoSomething()
{
    var A = await DoSomethingElse();
    MyInt += A.Result();
}

有可能当执行从await调用恢复时,我们会在另一个线程中,而MyInt + = A会将A添加到错误的MyInt中吗?

2 个答案:

答案 0 :(得分:1)

是的,无法保证在同一个线程上恢复执行。但您可以使用AsyncLocal代替 https://msdn.microsoft.com/en-us/library/dn906268(v=vs.110).aspx

答案 1 :(得分:1)

我认为@khoroshevj的答案是不完整的。这不简单。

如果,await,当有同步上下文可用时,它将被捕获,您将在该上下文中恢复,因为您没有明确告诉它它不需要{{1} }。请注意,您可以使用ConfigureAwait(false)在相同的上下文中恢复,因为这不是切换上下文的指令,它表示如果运行时决定最佳,则可以在不同的上下文中恢复。

所以,几乎如果这不是一个控制台应用程序而你没有设置一个新的ConfigureAwait(false),那么你将从你离开的地方恢复。

如果SynchronizationContext.Current或其相关调用堆栈中的任何内容也访问了threadlocal变量,那么您将遇到麻烦。

为了安全起见,您应该使用DoSomethingElse(),但您显示的代码应该按预期工作。