AspNet同步上下文
-
11-12-2019 - |
题
尝试使用新的 C# 5 异步模型,这让我感到惊讶 AspNetSynchronizationContext
是一个内部类(以及 AspNetSynchronizationContextBase
根据)。因此无证。但在 ASP.NET 代码中使用 async/await 功能时,了解它的作用非常重要。我纠正了吗 做 保证你的延续会得到相同的结果 HttpContext.Current
作为原始呼叫者?它 才不是 保证延续将在与调用者相同的线程上执行?
如果后一个假设不成立并且我得到原始线程,我是否可以确保在延续中获得相同的线程上下文?我的意思是与线程和线程本地存储相关的主体/文化?这很重要,因为 ASP.NET 本地化依赖于线程的区域性,而我的应用程序依赖于 .NET 角色安全模型(线程的主体)。
解决方案
我是否正确,它确实保证您的延续将获得与原始调用者相同的 HttpContext.Current ?它不保证延续将在与调用者相同的线程上执行?
是的, HttpContext.Current
被保留,是的,延续可以在不同的线程上执行。
我的意思是与线程和线程本地存储相关的主体/文化?这很重要,因为 ASP.NET 本地化依赖于线程的区域性,而我的应用程序依赖于 .NET 角色安全模型(线程的主体)。
普通线程本地存储丢失。您可以通过使用来缓解这种情况 LogicalCallContext
(其流动与 ExecutionContext
),但与 async
直接引用变量会更容易。
本金始终被保留;否则将会存在安全风险。这与 ExecutionContext
.
我相信文化随着 AspNetSynchronizationContext
, ,但我还没有对此进行测试 .NET 4.5的新实现.
你可能会发现我的 MSDN 文章关于 SynchronizationContext
有帮助。它不是官方文档(我不在微软工作),但至少它是一些东西。请注意, AspNetSynchronizationContext
该文章中引用的现在称为 LegacyAspNetSynchronizationContext
在 .NET 4.5 中。
另一个很棒的资源是 Stephen Toub 的 ExecutionContext
与 SynchronizationContext
.
其他提示
好吧,虽然始终保证捕获 ExecutionContext,但在同一个 SynchronizationContext 上捕获和运行执行取决于 Awaiter。
最常见的等待者(由 GetAwaiter() 方法返回的类型,当您“等待”某些内容时在内部调用)是由 Task.GetAwaiter() 返回的 TaskAwaiter。默认情况下,TaskAwaiter 将捕获当前的 SynchronizationContext 并在捕获的 SynchronizationContext 上运行延续委托. 。这意味着,您将能够在方法的其余部分中使用 HttpContext.Current,并且您不介意它将作为延续运行。因此,此代码将按预期工作(您编写“B”的部分将在与第一行相同的同步上下文上运行):
HttpContext.Current.Response.Write("A");
await Task.Delay(1000);
HttpContext.Current.Response.Write("B")
您可以使用以下方法更改此行为 Task.ConfigureAwait(false)
方法,告诉等待者不要将方法的其余部分封送回原始 SynchronizationContext。
当然,如果您在调用的异步方法中使用 Task.Run 或 Task.Factory.StartNew,则您有责任再次捕获 SynchronizationContext。
祝你好运。