Asp.net SynchronizationContext 为异步延续锁定 HttpApplication?
Posted
技术标签:
【中文标题】Asp.net SynchronizationContext 为异步延续锁定 HttpApplication?【英文标题】:Asp.net SynchronizationContext locks HttpApplication for async continuations? 【发布时间】:2012-07-06 21:02:25 【问题描述】:This commentStephen Cleary 这么说:
AspNetSynchronizationContext
是最奇怪的实现。它将Post
视为同步而非异步,并且使用锁一次执行一个委托。
同样,the article that he wrote on synchronization contexts 并在该评论中链接到:
从概念上讲,AspNetSynchronizationContext 的上下文是复杂的。在异步页面的生命周期中,上下文仅从 ASP.NET 线程池中的一个线程开始。异步请求启动后,上下文不包含任何线程。当异步请求完成时,执行其完成例程的线程池线程进入上下文。这些可能是发起请求的线程,但更有可能是操作完成时恰好空闲的线程。
如果多个操作一次完成同一个应用程序,AspNetSynchronizationContext 将确保它们一次执行一个。它们可以在任何线程上执行,但该线程将具有原始页面的标识和文化。
挖掘反射器似乎可以验证这一点,因为它在调用任何回调时会锁定HttpApplication
。
锁定应用对象似乎很可怕。所以我的第一个问题:这是否意味着今天,整个应用程序的所有异步完成都一次执行一个,即使是源自具有单独 HttpContexts 的单独线程上的单独请求的那些?对于任何 100% 使用异步页面(或 MVC 中的异步控制器)的应用程序来说,这不是一个巨大的瓶颈吗?如果不是,为什么不呢?我错过了什么?
此外,在 .NET 4.5 中,似乎有一个新的 AspNetSynchronizationContext
,旧的重命名为 LegacyAspNetSynchronizationContext
,并且仅在未设置新的应用程序设置 UseTaskFriendlySynchronizationContext
时使用。所以问题 #2:新的实现会改变这种行为吗?否则,我想随着新的 async/await 支持通过同步上下文封送完成,这种瓶颈会更频繁地被注意到。
this forum post 的答案(从 SO 答案here 链接)表明这里发生了根本性的变化,但我想弄清楚那是什么以及哪些行为得到了改进,因为我们有一个 .NET 4 MVC 3几乎 100% 异步操作方法调用 Web 服务的应用程序。
【问题讨论】:
我怀疑现有行为被认为“足够好”。请记住,异步操作本身是独立的;只有它们的完成例程(和延续)是同步的。此外,异步页面在 4.5 之前很难;目前大多数 ASP.NET 应用程序都是同步的。 而且我还没有机会查看新的 ASP.NET 同步上下文。事实上,上周末刚刚安装了 VS2012RC 的 4.5!但如果没有其他人,我最终会在这里回答。 请做。您将成为该主题最权威的消息来源之一。 【参考方案1】:让我回答你的第一个问题。在您的假设中,您没有考虑单独的 ASP.NET 请求由不同的 HttpApplication 对象处理的事实。 HttpApplication 对象存储在池中。一旦您请求一个页面,就会从池中检索一个应用程序对象,并在请求完成之前属于该请求。所以,我对你的问题的回答:
整个应用程序的所有异步完成一次执行一个,即使是源自具有单独 HttpContexts 的单独线程上的单独请求的异步完成
是:不,他们没有
单独的请求由单独的 HttpApplication 对象处理,锁定的 HttpApplication 只会影响单个请求。 同步上下文是一个强大的东西,它可以帮助开发人员同步对共享(在请求范围内)资源的访问。这就是为什么所有回调都在锁定下执行的原因。同步上下文是基于事件的同步模式的核心。
【讨论】:
具有讽刺意味的是,我今天早上在上班路上思考***.com/questions/9413585/… 时才意识到这一点。您对每个请求单独 HttpApplication 的响应是绝对正确的。感谢您的洞察力。以上是关于Asp.net SynchronizationContext 为异步延续锁定 HttpApplication?的主要内容,如果未能解决你的问题,请参考以下文章