13

Stephen Cleary的评论是这样说的:

AspNetSynchronizationContext是最奇怪的实现。它视为Post同步而不是异步,并使用锁一次执行一个委托

同样,他写的关于同步上下文并在该评论中链接到的文章表明:

从概念上讲,AspNetSynchronizationContext 的上下文是复杂的。在异步页面的生命周期中,上下文仅从 ASP.NET 线程池中的一个线程开始。异步请求启动后,上下文不包含任何线程。当异步请求完成时,执行其完成例程的线程池线程进入上下文。这些可能是发起请求的相同线程,但更有可能是在操作完成时碰巧空闲的任何线程。

如果同一应用程序一次完成多个操作,AspNetSynchronizationContext 将确保它们一次执行一个。它们可以在任何线程上执行,但该线程将具有原始页面的身份和文化。

挖掘反射器似乎可以验证这一点,因为它HttpApplication在调用任何回调时会锁定。

锁定应用程序对象似乎很可怕。所以我的第一个问题是:这是否意味着今天,整个应用程序的所有异步完成都一次执行一个,即使是源自具有单独 HttpContext 的单独线程上的单独请求的那些?对于任何 100% 使用异步页面(或 MVC 中的异步控制器)的应用程序来说,这不是一个巨大的瓶颈吗?如果不是,为什么不呢?我错过了什么?

此外,在 .NET 4.5 中,似乎有一个新AspNetSynchronizationContext的,旧的被重命名LegacyAspNetSynchronizationContext,并且仅在UseTaskFriendlySynchronizationContext未设置新的应用程序设置时使用。所以问题 #2:新的实现会改变这种行为吗?否则,我想随着新的 async/await 支持通过同步上下文封送完成,这种瓶颈会更频繁地被注意到。

这个论坛帖子的答案(从这里的 SO 答案链接)表明这里发生了根本性的变化,但我想弄清楚那是什么以及哪些行为得到了改进,因为我们有一个 .NET 4 MVC 3 应用程序,它几乎100% 异步操作方法进行 Web 服务调用。

4

1 回答 1

12

让我回答你的第一个问题。在您的假设中,您没有考虑单独的 ASP.NET 请求由不同的 HttpApplication 对象处理的事实。HttpApplication 对象存储在池中。一旦您请求一个页面,就会从池中检索一个应用程序对象,并在请求完成之前属于该请求。所以,我对你的问题的回答:

整个应用程序的所有异步完成一次执行一个,即使是源自具有单独 HttpContext 的单独线程上的单独请求的完成

是:不,他们没有

单独的请求由单独的 HttpApplication 对象处理,锁定的 HttpApplication 只会影响单个请求。同步上下文是一个强大的东西,它可以帮助开发人员同步对共享(在请求范围内)资源的访问。这就是为什么所有回调都在锁定下执行的原因。同步上下文是基于事件的同步模式的核心。

于 2012-07-31T06:02:27.913 回答