AspNetSynchronizationContext

Use*_*rol 22 .net asp.net asynchronous async-await c#-5.0

试图使用新的C#5异步模型,令我惊讶的AspNetSynchronizationContext是内部类(以及AspNetSynchronizationContextBase基础).因而无证.但是,在ASP.NET代码中使用async/await功能时,了解它的作用至关重要.我是否正确,它确实保证您的延续将与HttpContext.Current原始呼叫者相同?它保证continuation将在与调用者相同的线程上执行吗?

如果后一个假设不正确并且我得到原始线程,我可以确保在continuation中获得相同的线程上下文吗?我的意思是与线程和线程本地存储相关的主体/文化?这很重要,因为ASP.NET本地化依赖于线程的文化,而我的应用程序依赖于.NET角色安全模型(线程的主体).

Ste*_*ary 25

我是否正确它确实保证你的延续将获得与原始调用者相同的HttpContext.Current?它不保证continuation将在与调用者相同的线程上执行吗?

是的,HttpContext.Current保留,是的,延续可以在不同的线程上执行.

我的意思是与线程和线程本地存储相关的主体/文化?这很重要,因为ASP.NET本地化依赖于线程的文化,而我的应用程序依赖于.NET角色安全模型(线程的主体).

普通的线程本地存储丢失了.您可以通过使用LogicalCallContext(与之一起流动ExecutionContext)来缓解这种情况,但使用async它更容易直接引用变量.

校长总是被保留下来; 否则将是一种安全风险.这流淌着ExecutionContext.

我相信文化随之流动AspNetSynchronizationContext,但我还没有在.NET 4.5的新实现上对此进行测试.


您可能会发现我的MSDN文章SynchronizationContext有用.这不是官方文档(我不为微软工作),但至少它是一些东西.请注意,该AspNetSynchronizationContext文章中引用的内容现在LegacyAspNetSynchronizationContext在.NET 4.5中调用.

另一个伟大的资源是斯蒂芬Toub的ExecutionContext对比SynchronizationContext.


Sha*_*rtz 5

好吧,虽然始终保证捕获ExecutionContext,但在相同的SynchronizationContext上捕获和运行执行取决于Awaiter.

最常见的awaiter(GetAwaiter()方法返回的类型,当你"等待"某些东西时内部调用)是由Task.GetAwaiter()返回的TaskAwaiter.默认情况下,TaskAwaiter 将捕获当前的SynchronizationContext并在捕获的SynchronizationContext上运行continuation委托.这意味着,您将能够在方法的其余部分中使用HttpContext.Current,并且您不介意它将作为延续运行.因此,此代码将按预期工作(您写入"B"的部分将在与第一行相同的synchronizationcontext上运行):

HttpContext.Current.Response.Write("A");
await Task.Delay(1000);
HttpContext.Current.Response.Write("B")
Run Code Online (Sandbox Code Playgroud)

您可以使用Task.ConfigureAwait(false)方法更改此行为,该方法告诉awaiter不要将方法的其余部分封送回原始SynchronizationContext.

当然,如果您在正在调用的异步方法中使用Task.Run或Task.Factory.StartNew,则您有责任再次捕获SynchronizationContext.

祝你好运.