Книга: ASP.NET MVC Framework
Паттерн Event
Паттерн Event
Согласно этому паттерну, метод действия разделяется на два метода: запуска и завершения:
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)
{
...
}
Чтобы упростить процесс, существует альтернатива прямому инкрементированию и декрементированию. С помощью стандартной части AsyncController
метода AsyncManager.RegisterTask
можно использовать связку из паттернов IAsyncResult
и Event
. Рассмотрим на примере:
public void XXX(Guid? userId)
{
AsyncManager.RegisterTask(
callback => BeginXXX(userId, callback, null),
asyncResult =>
{
UserData userData = EndXXX(asyncResult);
AsyncManager.Parameters["userData"] = userData;
}
);
}
public ActionResult XXXCompleted(UserData userData)
{
// ...
}
Во фрагменте кода используется паттерн Event
, согласно которому создается два метода: xxx
и xxxCompleted
. Метод xxx
регистрирует асинхронную задачу с помощью механизма AsyncManager.RegisterTask
, который принимает два параметра: анонимные функции, осуществляющие логику паттерна IAsyncResult
. Первая функция вызывает метод Beginxxx
, который выполняет некую асинхронную операцию. Вторая анонимная функция выполняется тогда, когда асинхронная операция заканчивается и ей передаются результаты вызова Beginxxx
. Задача второй анонимной функции состоит в том, чтобы, используя метод Endxxx
паттерна IAsyncResult
, получить значения параметров для метода XXXCompleted
.
Преимущество данной связки паттернов состоит в том, что разработчику предоставляется возможность создавать несколько следующих подряд вызовов механизма AsyncManager.RegisterTask
, которые выполняют разные асинхронные операции и формируют результаты разных параметров для метода XXXCompleted
. Так как механизм AsyncManager.RegisterTask
самостоятельно отслеживает инкремент и декремент свойства AsyncManager.OutstandingOperations
, разработчику предлагается более безопасный и простой механизм создания нескольких асинхронных операций в одном запросе.
- Паттерн Delegate
- Паттерн IAsyncResult
- EVENT MEMORY SIZE
- 15.3.1. Shared Library Events in GDB
- 3.5.2. Distributed Deadlock Prevention
- Enabling and disabling event logging
- 8.3 Event Registers
- 8.3.1 Event Register Control Blocks
- 8.3.2 Typical Event Register Operations
- 8.3.3 Typical Uses of Event Registers
- 15.6.2 Asynchronous Event Notification Using Signals
- 16.3.5 Deadlock Prevention