AspNetSynchronizationContext
是最奇怪的实现。它将Post
视为同步而非异步,使用锁定一次执行一个代理。
同样地,the article that he wrote on synchronization contexts与该评论中的链接表明:
从概念上讲,AspNetSynchronizationContext的上下文很复杂。在异步页面的生命周期中,上下文仅从ASP.NET线程池中的一个线程开始。异步请求启动后,上下文不包含任何线程。当异步请求完成时,执行其完成例程的线程池线程进入上下文。这些可能是发起请求的线程相同,但更可能是在操作完成时任何线程都是空闲的。
如果同一个应用程序一次完成多个操作,AspNetSynchronizationContext将确保它们一次执行一个。它们可以在任何线程上执行,但该线程将具有原始页面的标识和文化。
挖掘反射器似乎验证了这一点,因为它在调用任何回调时锁定HttpApplication
。
锁定应用程序对象看起来像是可怕的东西。所以我的第一个问题:这是否意味着今天,整个应用程序的所有异步完成都会一次执行一个,即使是源自具有单独HttpContexts的单独线程上的单独请求的那些?对于任何100%使用异步页面(或MVC中的异步控制器)的应用程序来说,这不是一个巨大的瓶颈吗?如果没有,为什么不呢?我错过了什么?
此外,在.NET 4.5中,看起来有一个新的AspNetSynchronizationContext
,而旧的LegacyAspNetSynchronizationContext
重新命名为UseTaskFriendlySynchronizationContext
,仅在未设置新应用设置{{1}}时使用。问题2:新实现是否会改变这种行为?否则,我想通过同步上下文中新的async / await支持编组完成,这种瓶颈将会更频繁地被注意到。
this forum post的回答(从SO回答here链接)表明这里发生了根本性的变化,但我希望明确这是什么以及哪些行为有所改善,因为我们有一个。 NET 4 MVC 3应用程序,它几乎是100%异步操作方法,可以进行Web服务调用。
答案 0 :(得分:11)
让我回答你的第一个问题。在您的假设中,您没有考虑不同的HttpApplication对象处理单独的ASP.NET请求这一事实。 HttpApplication对象存储在池中。一旦您请求页面,就会从池中检索应用程序对象,并且该应用程序对象在完成之前属于该请求。所以,我对你的问题的回答:
整个应用程序的所有异步完成一次执行一个,即使是源自具有单独HttpContexts的单独线程上的单独请求的
是:不,他们不
单独的请求由单独的HttpApplication对象处理,锁定的HttpApplication仅影响单个请求。 同步上下文是一个强大的功能,可帮助开发人员同步对共享(在请求范围内)资源的访问。这就是所有回调都在锁定下执行的原因。同步上下文是基于事件的同步模式的核心。