Вход/Регистрация
Интернет-журнал "Домашняя лаборатория", 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 обрабатывает синхронные запросы, уже было рассмотрено ранее. Теперь изучим ветви его кода, ответственные за обработку асинхронных запросов.

  • Читать дальше
  • 1
  • ...
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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