2012-02-23 2 views
3

В какой степени асинхронные события HttpApplication (например, зарегистрированные с использованием AddOnEndRequestAsync и друзей) асинхронны? Является ли IIS ожидающим, чтобы все асинхронные события, запущенные для конкретного события, завершились, прежде чем переходить к следующему событию, или они «стреляют и забывают»?Выполняют ли асинхронные события HttpApplication, пока они не вернутся?

ответ

3

Непонятно, какие именно операции выполняются в режиме интегрированного конвейера, но я могу рассказать вам, что я вижу для неинтегрированного случая, и семантика должна оставаться неизменной.

Короткий ответ заключается в том, что каждый обработчик событий запускается последовательно, синхронно или асинхронно, а следующий не запускается до тех пор, пока предыдущий не завершится.

Вы можете проследить это через исходный код.

Запрос приходит и хранится в очереди. Как правило, когда HttpRuntime отменяет запрос, он инициализирует HttpApplication для запроса, вызывая его метод InitInternal, передавая HttpContext в качестве аргумента.

HttpApplication.InitInternal инициализирует новый класс HttpApplication.ApplicationStepManager для случая не интегрированного режима. Затем вы можете увидеть, что он называет метод BuildSteps. Это создает ArrayList для хранения шагов и конструкций и сохраняет все этапы. В частности, эти этапы представляют собой реализации интерфейса IExecuteStep. В конечном счете, когда все шаги добавлены, список завершается копированием его в массив и сохранением его для более позднего элемента var _execSteps.

Существует несколько источников шагов, но наиболее часто используемыми вы видите HttpApplication.CreateEventExecutionSteps, который принимает тип события (начало запроса, авторизация и т. Д.) И массив шагов, чтобы добавить его шаги для этого события. Если вы свернете на CreateEventExecutionSteps, вы увидите, что он добавляет IExecuteStep для каждого асинхронного и обработчика синхронизации, о котором он знает, из таблиц AsyncEvents и Events, соответственно. Интерфейс IExecuteStep сам по себе состоит из Execute и CompletedSynchronously.

Теперь остановитесь и посмотрите на один из методов Добавить, как вы упомянули, AddOnEndRequestAsync, и вы можете увидеть его, чтобы добавить информацию об обработчике async в таблицу AsyncEvents. CreateEventExecutionSteps будет проходить через этот стол, и для каждого обработчика будет создан AsyncEventExecutionStep.

Обратно к потоку запросов. После того, как HttpRuntime инициализирует HttpApplication для запроса, он вызывает свой метод BeginProcessRequest, который запускает ResumeSteps.

ResumeSteps является важным, когда вы можете увидеть, как этапы используются и что ждет стратегия ожидания в асинхронном случае. Вы можете видеть, что он поддерживает _currentStepIndex в массив шагов выполнения. В конце концов вы увидите, что он захватывает следующий шаг из массива и вызывает его метод Execute. Если на шаге сообщается, что его выполнение CompletedSynchronously, оно циклически и снова идет. Если нет, он позволяет методу закончить и войти в асинхронную абис.

Чтобы посмотреть, что произойдет в этом асинхронном случае, вы должны посмотреть на реализацию AsyncEventExecutionStep, которая была создана для обработчиков async. В своей реализации Execute вы видите, что он запускает обработчик начала и передает обратный вызов завершения. В конструкторе вы видите, что этот обратный вызов инициализирован методом, который в конечном итоге вызывает ... HttpApplication.ResumeSteps еще раз!

И так оно продолжается, выполняет шаги, синхронизирует или асинхронно, пока массив не переполняется, и в этот момент он «завершает» обработку запроса.

Дело в том, что вы можете четко видеть, что шаги, которые переводят обработчики событий, которые вы добавляете, выполняются один за другим, а также синхронизация или асинхронный процесс, следующие шаги не выполняются до тех пор, пока не будет выполнен текущий шаг. Ваш вопрос заключался в том, обрабатываются ли события один за другим таким образом, но, как вы видите, на самом деле он еще более гранулирован, причем каждый обработчик событий обрабатывается таким образом, поэтому каждый получает синхронизированный доступ к HttpContext и может работать без беспокоясь о том, остаются ли они «в правильной фазе» трубопровода.

Очевидно, что в этом исходном коде есть другие детали, yada yada, но это суть.

Смежные вопросы