Ожидать ли события асинхронного HttpApplication возврата? - PullRequest
3 голосов
/ 23 февраля 2012

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

1 Ответ

4 голосов
/ 31 июля 2012

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

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

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

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

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

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

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

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

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

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

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

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

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

...