System.Web.Mvc, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
Эти определения обработчиков необходимо заменить на следующие:
type="Microsoft.Web.Mvc.MvcHttpAsyncHandler, Microsoft.Web.Mvc"/>
verb="*" path="*.mvc" type="Microsoft.Web.Mvc.MvcHttpAsyncHandler,
Microsoft.Web.Mvc"/>
После всех изменений можно приступать к работе с асинхронными контроллерами. Для того чтобы класс контроллера стал асинхронным, необходимо наследовать его от класса AsyncController
:
public class SomeAsyncController : AsyncController
{
...
}
После этого конструктор по умолчанию, унаследованный от AsyncController
, определит новый вариант ActionInvoker
в виде экземпляра класса AsyncControllerActionInvoker
для того, чтобы выполнять асинхронные действия. Для реализации асинхронных действий механизм AsyncController
предлагает три паттерна, которые вы вольны использовать по отдельности либо смешивать их друг с другом: IAsyncResult, Event, Delegate
.
Паттерн IAsyncResult
предполагает, что разработчик сам создаст асинхронную операцию. Согласно этому паттерну, вместо одного метода действия с именем XXX создаются два метода, BeginXXX и EndXXX, со следующим определением параметров:
public IAsyncResult BeginXXX(Guid? userId, AsyncCallback callback, object state);
public ActionResult EndXXX(IAsyncResult asyncResult);
Этот паттерн работает следующим образом:
1. MVC принимает запрос на выполнение действия xxx.
2. Механизмы MVC и AsyncController вызовут BeginXXX точно так же, как и любое другое синхронное действие.
3. Предполагается, что метод Beginxxx создаст некую тяжеловесную асинхронную операцию, например файловое чтение или запрос к базе данных, и использует переданную через параметры функцию обратного вызова callback
для вызова после завершения асинхронной операции.
4. После выполнения асинхронной операции будет вызван второй метод Endxxx, которому будет передан результат выполнения Beginxxx в виде экземпляра IAsyncResult
.
5. Метод Beginxxx, используя данные, полученные от Beginxxx, формирует обычный для всех действий результат в виде ActionResult
или его производных.
Согласно этому паттерну, метод действия разделяется на два метода: запуска и завершения:
public void XXX(Guid? userId);
public ActionResult XXXCompleted(...);
Метод xxx соответствует обычному синхронному действию и вызывается стандартно. Полный механизм работы данного паттерна состоит из следующих действий:
1. MVC принимает запрос на выполнение действия xxx.
2. Механизмы MVC и AsyncController вызовут XXX точно так же, как и любое другое синхронное действие.
3. Разработчик определяет внутри метода xxx асинхронную операцию, после запуска которой метод завершает свое выполнение.
4. Чтобы механизм асинхронных контроллеров мог определить, когда следует вызвать XXXCompleted, разработчик должен воспользоваться свойством AsyncManager.OutstandingOperations
, которое является стандартным для класса контроллера AsyncController
.
5. Разработчик инкрементирует AsyncManager.OutstandingOperations
при создании каждого асинхронного процесса и заботится о том, чтобы по завершению процесса свойство AsyncManager.OutstandingOperations
было декрементировано.
6. Механизм AcyncControllerActionInvoker
следит за свойством AsyncManager.OutstandingOperations
и вызывает XXXCompleted
, когда это свойство обнулится, что означает завершение работы всех асинхронных процессов.
7. Параметры для XXXCompleted
определяет разработчик. Для того чтобы AcyncControllerActionInvoker
мог правильно выполнить XXXCompleted
и передать необходимые параметры, разработчик заполняет специальную структуру AsyncManager.Parameters
, которая является частью класса AsyncController
. Структура AsyncManager.Parameters
заполняется при работе метода xxx.
8. После завершения работы XXX механизм AcyncControllerActionInvoker
вызывает метод XXXCompleted
с набором параметров на базе AsyncManager.Parameters
.
9. Используя переданные параметры, метод XXXCompleted
возвращает стандартный результат в виде ActionResult
или его производных.
Следующий фрагмент кода демонстрирует реализацию паттерна Event
:
public void SelectUser(Guid? userId)
{
As
yncManager.Parameters["userData''] = new UserData();
As
yncManager.OutstandingOperations.Increment();
ThreadPool.QueueUserWorkItem(o =>
{
Thread.Sleep(2000);
AsyncManager.OutstandingOperations.Decrement();
}, null);
}
public ActionResult SelectUserCompleted(UserData userData)
{
Читать дальше
Конец ознакомительного отрывка
Купить книгу