ConfigureAwait(false) 维护线程身份验证,但默认情况下不

Posted

技术标签:

【中文标题】ConfigureAwait(false) 维护线程身份验证,但默认情况下不【英文标题】:ConfigureAwait(false) maintains thread authentication but by default it doesn't 【发布时间】:2019-04-27 04:14:48 【问题描述】:

我有一个简单的 Web API 操作方法,其中包含以下代码 sn-p

Debug.WriteLine("Before async method call id: " + Thread.CurrentThread.ManagedThreadId);
            Debug.WriteLine("Before async method call auth: " + Thread.CurrentPrincipal.Identity.IsAuthenticated);

            var result = await SomeAsyncMethod();

            Debug.WriteLine("After async method call id: " + Thread.CurrentThread.ManagedThreadId);
            Debug.WriteLine("After async method call auth: " + Thread.CurrentPrincipal.Identity.IsAuthenticated);

此代码打印出以下内容:

Before async method call id: 257
Before async method call auth: True
After async method call id: 268
After async method call auth: False

请注意,在 await 调用之后,主线程现在是未经身份验证的。但是,如果我像下面这样使用 ConfigureAwait(false):

Debug.WriteLine("Before async method call id: " + Thread.CurrentThread.ManagedThreadId);
            Debug.WriteLine("Before async method call auth: " + Thread.CurrentPrincipal.Identity.IsAuthenticated);

            var result = await SomeAsyncMethod().ConfigureAwait(false);

            Debug.WriteLine("After async method call id: " + Thread.CurrentThread.ManagedThreadId);
            Debug.WriteLine("After async method call auth: " + Thread.CurrentPrincipal.Identity.IsAuthenticated);

我看到下面的输出:

Before async method call id: 268
Before async method call auth: True
After async method call id: 242
After async method call auth: True

我对 ConfigureAwait(false) 的理解是代码在不同的线程中运行 不知道原始线程的上下文(身份验证等)。因此,它最适合第三方库。

根据以上观察,我有以下问题-

    异步调用前后线程 ID 的变化。不应该在调用异步方法的主线程上恢复吗? 即使调用在不同的线程上恢复(如示例中所示),它是否应该在主线程的相同上下文中恢复(即 IsAuthenticated 必须为真)?为什么使用 ConfigureAwait(false) 验证保持 true 而不是其他情况?

谢谢!

【问题讨论】:

***.com/questions/21390186/… 可能重复。 【参考方案1】:

特定线程在 ASP.NET 中并不重要。请求由线程池中的任何可用线程提供服务。

重要的是同步上下文。

ConfigureAwait(false) 指示编译器生成的状态机将延续调度到线程池,而不是将它们发布到捕获的同步上下文(如果已捕获)。

同步上下文使用正确的线程数据和线程静态设置调度线程池线程。

您不应在操作方法上调用 ConfigureAwait(false),因为您无法保证线程数据是您所期望的。

不管是否有同步上下文,异步代码都会在线程间流动逻辑调用上下文。并且,随之而来的是当前的本金。

【讨论】:

谢谢保罗。我明白这一点;但是,我正在寻找有关上述特定场景/用例的更多解释。您的答案更多是在概念层面上。

以上是关于ConfigureAwait(false) 维护线程身份验证,但默认情况下不的主要内容,如果未能解决你的问题,请参考以下文章

***请求上的 ConfigureAwait(false)

为整个项目/dll 设置 ConfigureAwait(false)

ConfigureAwait(false) 与将同步上下文设置为 null

您可以在没有线程安全的情况下使用 ConfigureAwait(false) 吗?

ConfigureAwait(false) 不会使延续代码在另一个线程中运行

为啥总是推荐在每一行上写 ConfigureAwait(false) 并且我真的需要它吗?