Asp.net 异步HttpApplication事件是否会等待它们返回?
HttpApplication异步事件(例如使用Asp.net 异步HttpApplication事件是否会等待它们返回?,asp.net,iis,asynchronous,httpapplication,Asp.net,Iis,Asynchronous,Httpapplication,HttpApplication异步事件(例如使用AddOnEndRequestAsync和friends注册的事件)在多大程度上是异步的?IIS是等待为某个特定事件触发的所有异步事件在进入下一个事件之前完成,还是“触发并忘记”?在集成管道模式下运行时,我不清楚具体的工作原理,但我可以告诉您我看到的非集成情况,语义应该保持不变 简单的回答是,每个事件处理程序都是串联触发的,无论是同步还是异步的,直到前一个事件处理程序完成后才触发下一个事件处理程序 您可以通过源代码跟踪这一点 请求进入并存储在队列中
AddOnEndRequestAsync
和friends注册的事件)在多大程度上是异步的?IIS是等待为某个特定事件触发的所有异步事件在进入下一个事件之前完成,还是“触发并忘记”?在集成管道模式下运行时,我不清楚具体的工作原理,但我可以告诉您我看到的非集成情况,语义应该保持不变
简单的回答是,每个事件处理程序都是串联触发的,无论是同步还是异步的,直到前一个事件处理程序完成后才触发下一个事件处理程序
您可以通过源代码跟踪这一点
请求进入并存储在队列中。通常,当HttpRuntime
将请求出列时,它通过调用其InitInternal
方法初始化请求的HttpApplication
,并将HttpContext
作为参数传递
HttpApplication.InitInternal
为非集成模式案例初始化一个新的HttpApplication.ApplicationStepManager
类。然后可以看到它调用了BuildSteps
方法。这将创建一个ArrayList
来存储步骤,并构造和存储所有步骤。具体来说,这些步骤是IExecuteStep
接口的实现。最后,当添加所有步骤时,通过将其复制到数组并保存到成员var\u execSteps
中,列表将最终确定
步骤有多个来源,但您将看到的最常用的是HttpApplication.CreateEventExecutionSteps
,它采用事件类型(开始请求、授权等)和步骤数组为事件添加步骤。如果深入到CreateEventExecutionSteps
中,您可以看到它分别从AsyncEvents
和Events
表中为它知道的每个异步和同步处理程序添加了一个IExecuteStep
。IExecuteStep
接口本身基本上由一个Execute
方法和一个CompletedSynchronously
标志组成
现在,暂停并回顾一下您提到的添加方法之一,AddOnEndRequestAsync
,您可以看到它将有关异步处理程序的信息添加到AsyncEvents
表中CreateEventExecutionSteps
将遍历此表,并为添加的每个处理程序构造一个AsyncEventExecutionStep
返回到请求流。HttpRuntime
为请求初始化HttpApplication
后,它调用其BeginProcessRequest
方法,该方法触发resumesteeps
resumesteeps
是一个重要的步骤,在这里您可以看到如何使用这些步骤以及异步情况下的等待策略。您可以看到它在执行步骤数组中维护一个\u currentStepIndex
。最终,您会看到它从数组中抓取下一步并调用其Execute
方法。如果该步骤报告其执行已同步完成,则会循环并再次执行。如果没有,它将让方法完成并进入异步深渊
要查看在这种异步情况下会发生什么,您必须查看为异步处理程序创建的AsyncEventExecutionStep
实现。在其Execute
实现中,您可以看到它启动begin处理程序并传入一个完成回调。在构造函数中,您会看到此回调初始化为最终调用<代码>HttpApplication.ResumeSteps再次
因此,它会继续运行,执行同步或异步步骤,直到数组溢出,并在该点“完成”请求处理
关键是,您可以清楚地看到,转换为您添加的事件处理程序的步骤是一个接一个地执行的,并且无论是同步还是异步,在当前步骤完成之前都不会执行以下步骤。您的问题是事件是否以这种方式一个接一个地处理,但正如您所看到的,事实上它更细粒度,每个事件处理程序都以这种方式处理,因此每个事件处理程序都可以同步访问HttpContext,并且可以运行,而不必担心它们是否仍处于管道的“正确阶段”
很明显,源代码中还有其他细节,yada-yada,但这是要点