为什么在使用ConfigureAwait(false)后还要保留上下文?

6

我有以下异步代码:

// Main system culture is English here
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("es");

WriteLine($"{Thread.CurrentThread.ManagedThreadId}:Culture:{Thread.CurrentThread.CurrentCulture}");

await Task.Delay(1).ConfigureAwait(false);

WriteLine($"{Thread.CurrentThread.ManagedThreadId}:Culture:{Thread.CurrentThread.CurrentCulture}");

我期望的结果是,在等待后有一个不同的线程 ID,而这个新的线程 ID 再次具有未修改的系统区域设置。
但事实并非如此;线程确实与以前不同,但是区域设置某种方式从先前的线程中流动。
如果我使用 ConfigureAwait 建议不需要保留 SynchronisationContext,为什么它还保留了区域设置呢?我的理解是区域设置不存储在 ExecutionContext 上,因此我不确定为什么会发生这种情况。
这是一个控制台应用程序。
完整示例代码:https://pastebin.com/raw/rE6vZ9Jm

你可能已经知道了,但我还是提一下:由于你正在构建一个控制台应用程序,所以没有SynchronizationContext,因此ConfigureAwait(false)实际上不会改变你发布的代码的行为 - 至少不是你期望的方式。 - Kirill Shlenskiy
@KirillShlenskiy 感谢您的评论;我已经知道了,但是因为我最初没有指定它是控制台应用程序(后来进行了编辑),所以我添加了它。 - user4388177
2个回答

8

这是.NET 4.6的预期行为。

Julien无法重现此问题的原因是他可能针对较低版本的框架(例如在4.5.2中,文化传递不会发生)。

这里是官方文档

特别注意以下内容:

...... 从目标 .NET Framework 4.6 的应用程序开始,默认情况下,异步操作继承启动它们的线程的 CurrentCulture 和 CurrentUICulture 属性的值。 如果当前区域设置或当前 UI 区域设置与系统区域设置不同,则当前区域设置会跨线程边界,并成为执行异步操作的线程池线程的当前区域设置。


太棒了,谢谢。我确实使用的是4.6版本,改成4.5版本就解决了问题。 - user4388177

1
在一个新的VS2017控制台项目上进行快速测试,输出如下(en-GB是我的默认文化设置):
1:Culture:es
4:Culture:en-GB

这正是你(和我)所期望的。也许还有其他因素在独立地设定文化?

这是一个非常简单的控制台应用程序,除了Main方法和Program类之外几乎没有其他内容,所以很容易让人感到困惑。我将分享完整的源代码。 - user4388177
尝试将目标框架设置为4.6,结果输出如下:1:Culture:es 4:Culture:es - Julien Adam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接