尝试使用新的 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 的 ExecutionContextSynchronizationContext.

其他提示

好吧,虽然始终保证捕获 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。

祝你好运。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top