MVC 事件是否重叠?

Do MVC events overlap?

MvcApplication 在哪个时间点调用 HttpAplications 事件,例如:

    ...
    public event EventHandler PreSendRequestHeaders;
    public event EventHandler PostResolveRequestCache;
    public event EventHandler PreSendRequestContent;
    public event EventHandler PostMapRequestHandler;
    public event EventHandler PostLogRequest;
    public event EventHandler RequestCompleted;
    ...

它怎么知道前一个Handler(上一个事件的)什么时候结束了?Handler是同步调用一个接一个就绪的吗? 举个例子:

    // gets called through HttpApplication.BeginRequest event
    protected void Application_BeginRequest() {
         Thread.Sleep(60000);
         // Waits very long
         Debug.WriteLine("begin");
    }

    // gets invoked after BeginRequest by the Event AuthenticateRequest
    // Event is used to attach Authentication related operations to it 
    protected void Application_AuthenticateRequest() {
         Debug.WriteLine("authentication in process");
    }


    // Output:
    // begin
    // authentication in process

通常情况下,一个接一个调用的事件处理程序的执行会重叠。这些没有。为什么?

我在另一个 post 中找到了答案:are C# events synchronous?

它表示通过 Invoke 方法而不是 InvokeAsync 方法调用事件或组合后备委托,这意味着默认情况下同步调用 .Net 事件。

有一个例外:

Raising an event does block the thread if the event handlers are all implemented synchronously.

这意味着内部 HttpApplication 正在一个接一个地调用附加的处理程序,然后如果所有事件都是同步的则继续下一个事件。这使得在一个处理程序中所做的更改可以在稍后添加到事件的另一个处理程序中覆盖。

The event handlers are executed sequentially, one after another, in the order they are subscribed to the event.

因为我知道重要的 MVC 事件处理程序是同步的,所以这应该不是问题。但是一旦一个附加的事件处理程序是 aysnc,组合委托(支持事件委托)就是 运行 async.

  class Program
{
    static void Main(string[] args)
    {
        var foo = new Foo();
        foo.OnWork += async (e, v) =>
        {
           await Task.Run(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine(v);
            });
        };
        foo.OnWork += (e, v) =>
        {
            Console.WriteLine("2." + v);
        };

        foo.DoWork();
        foo.DoWork();

        Console.ReadLine();
    }
}

public class Foo
{
    public event EventHandler<int> OnWork;

    private int val = 1;

    public void DoWork()
    {
        OnWork?.Invoke(this, val++);
    }
}

// Output:
// 2.1
// 2.2
// 1
// 2

// Sometimes 1 and 2 are reversed because they are running in different Threads