Чтение онлайн

на главную - закладки

Жанры

Интернет-журнал "Домашняя лаборатория", 2007 №6
Шрифт:

Тут все в порядке, если только инкапсулированный вызов вложен в исполняемый синхронный вызов. Если же этот инкапсулированный вызов вложен в некоторый исходящий асинхронный вызов, то могут быть проблемы. Например, в данное время в данном домене синхронизации уже может выполняться некоторый синхронный вызов и параллельное выполнение еще одного вызова противоречит логике использования домена синхронизации (?!).

Теперь настало время рассмотреть код ранее упомянутого метода HandleWorkCompletion. Как и ранее рассмотрим только ту ветвь, которая связана с обработкой синхронных вызовов.

internal virtual void HandleWorkCompletion {

Workitem nextWork = null;

bool bNotify = false;

lock (_workItemQueue) {

if (_workItemQueue.Count >= 1) {

nextWork = (Workitem) _workltemQueue.Peek;

bNotify = true;

nextWork.SetSignaled;

}

else {

_locked = false;

}

}

if (bNotify) {

if (nextWork.IsAsync) {

.......

}

else {

lock(nextWork) {

Monitor.Pulse(nextWork);

}

}

}

}

Данный

метод вызывается по завершении обработки некоторой работы. В это время домен синхронизации еще блокирован (_locked == true).

Прежде всего блокируется очередь работ. Если она не пуста, мы получаем ссылку на работу (nextWork), стоящую в этой очереди первой (не извлекая ее из очереди) и устанавливаем флаг готовности данной работы к выполнению. Если же очередь пуста, домен синхронизации разблокируется (_locked = false). Это означает, что вновь пришедший синхронный вызов будет обработан сразу же без постановки в очередь.

Если в начале очереди находится синхронная работа (nextWork), то это означает, что имеется поток, который находится в состоянии ожидания того момента, когда работа nextWork будет готова к выполнению. Этот поток в свое время впал в состояние ожидания находясь в некоторой критической секции, в которую он попал заблокировав объект nextWork. Находясь в этой критической секции он был должен освободить эту блокировку, так как в то время работа nextWork была поставлена в очередь работ и этот поток не мог продолжить ее обработку. Теперь его пора разбудить. Это делает текущий поток, в котором выполняется код метода HandleWorkCompletion:

lock(nextWork) {

Monitor.Pulse(nextWork);

}

Текущий поток входит в критическую секцию (заблокировав nextWork) и уведомляет все заинтересованные потоки о том, что состояние объекта nextWork как-то изменилось. Эти находящиеся в состоянии ожидания потоки переходят в состояние готовности и по выходе текущего потока из данной критической секции пытаются захватить контроль над объектом nextWork. В нашем случае такой поток единственный и именно он ответственен за продолжение обработки вызова, инкапсулированного в работу nextWork. Конкретнее, это поток, выполняющий код метода HandieWorkRequest начиная со строки, следующей за строкой Monitor.Wait(work);

Как перехватчик обрабатывает асинхронные вызовы

Вновь

возвращаемся к классу SynchronizedServerContextSink, который реализует интерфейс IMessageSink. В этом интерфейсе объявлен метод AsyncProcessMessage, который и должен реализовать обработку асинхронных вызовов в перехватчике входящих вызовов. Вот так этот метод реализован в классе SynchronizedServerContextSink:

public virtual IMessageCtrl AsyncProcessMessage(

IMessage reqMsg, IMessageSink replySink) {

Workltem work = new WorkItem (

reqMsg,

_nextSink,

replySink);

work.SetAsync;

_property.HandleWorkRequest(work);

return null;

}

В данном случае мы имеем два входных параметра. Первый задает вызов в форме сообщения типа IMessage (как и в случае синхронного вызова). А вот второй параметр специфичен для асинхронных вызовов. Он задает ссылку на еще один перехватчик, который ответственен за доставку уведомления о завершении асинхронного вызова. И, наконец, возвращаемое значение имеет также специфический для асинхронных вызовов тип — IMessageCtrl. В .NET интерфейс IMessageCtrl объявляет единственный метод Cancel, с помощью которого можно прервать выполнение асинхронного вызова. В данном случае метод AsyncProcessMessage всегда возвращает null, не предоставляя такую возможность.

Функциональность данного метода вполне понятна. Пришедший асинхронный вызов инкапсулируется в работу work, далее для нее устанавливается флаг асинхронности, позволяющий различать синхронные и асинхронные работы, и, наконец, данная работа направляется на обработку в свойство синхронизации _property.

То, как метод HandleWorkRequest обрабатывает синхронные запросы, уже было рассмотрено ранее. Теперь изучим ветви его кода, ответственные за обработку асинхронных запросов.

Как свойство синхронизации обрабатывает инкапсулированный асинхронный вызов, полученный от перехватчика

Ниже приведена часть кода HandleWorkRequest, которая относится к обработке именно асинхронных вызовов:

internal virtual void HandieWorkRequest(Workltem work) {

bool bQueued;

if (!IsNestedCall(work._reqMsg)) {

if (work.IsAsync) {

bQueued = true;

lock (workltemQueue) {

work.SetWaiting;

_workltemQueue.Enqueue(work);

if ((!_locked) & &

(_workItemQueue.Count == 1)) {

work.SetSignaled;

_locked = true;

_asyncWorkEvent.Set;

}

}

}

else {

…..

}

}

else {

work.SetSignaled;

work.Execute;

}

}

Итак, если вызов не вложенный, происходит следующее. Блокируется очередь работ (текущий поток входит в критическую секцию)

Поделиться:
Популярные книги

Отборная бабушка

Мягкова Нинель
Фантастика:
фэнтези
юмористическая фантастика
7.74
рейтинг книги
Отборная бабушка

Этот мир не выдержит меня. Том 3

Майнер Максим
3. Первый простолюдин в Академии
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Этот мир не выдержит меня. Том 3

Тайный наследник для миллиардера

Тоцка Тала
Любовные романы:
современные любовные романы
5.20
рейтинг книги
Тайный наследник для миллиардера

Новые горизонты

Лисина Александра
5. Гибрид
Фантастика:
попаданцы
технофэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Новые горизонты

Меч Предназначения

Сапковский Анджей
2. Ведьмак
Фантастика:
фэнтези
9.35
рейтинг книги
Меч Предназначения

Циклопы. Тетралогия

Обухова Оксана Николаевна
Фантастика:
детективная фантастика
6.40
рейтинг книги
Циклопы. Тетралогия

Убивать чтобы жить 5

Бор Жорж
5. УЧЖ
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 5

(Не)свободные, или Фиктивная жена драконьего военачальника

Найт Алекс
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
(Не)свободные, или Фиктивная жена драконьего военачальника

На осколках разбитых надежд

Струк Марина
Любовные романы:
исторические любовные романы
5.00
рейтинг книги
На осколках разбитых надежд

Бывшие. Война в академии магии

Берг Александра
2. Измены
Любовные романы:
любовно-фантастические романы
7.00
рейтинг книги
Бывшие. Война в академии магии

Вернуть невесту. Ловушка для попаданки

Ардова Алиса
1. Вернуть невесту
Любовные романы:
любовно-фантастические романы
8.49
рейтинг книги
Вернуть невесту. Ловушка для попаданки

Сила рода. Том 3

Вяч Павел
2. Претендент
Фантастика:
фэнтези
боевая фантастика
6.17
рейтинг книги
Сила рода. Том 3

Все романы Роберта Шекли в одной книге

Шекли Роберт
2. Собрание сочинений Роберта Шекли в двух томах
Фантастика:
фэнтези
научная фантастика
5.00
рейтинг книги
Все романы Роберта Шекли в одной книге

Вечный. Книга IV

Рокотов Алексей
4. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга IV