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

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

Жанры

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

replyMsg = _nextSink.SyncProcessMessage(reqMsg);

if (bTopLevel) {

_property.SyncCallOutLCID = null;

if (bClear) {

LogicalCallContext cctxRet =

(LogicalCallContext)

replyMsg.Properties[Message.CallContextKey];

cctxRet.RemotingData.LogicalCalllD = null;

}

}

}

return replyMsg;

}

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

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

Прежде всего нужно узнать идентификатор исходящего вызова. Для этого получаем доступ к его контексту вызова

LogicalCallContext cctx =

(LogicalCallContext)

reqMsg.Properties[Message.CallContextKey];

и, затем, к самому идентификатору

String lcid = cctx.RemotingData.LogicalCallID;

Может оказаться, что в данный момент исходящий вызов (reqMsg) еще не имеет идентификатора. В таком случае присвоим ему новый еще не использованный идентификатор

bool bClear = false;

if (lcid == null) {

lcid = Identity.GetNewLogicalCalllD;

cctx.RemotingData.LogicalCalllD = lcid;

bClear = true;

}

Здесь статический метод GetNewLogicalCallID класса Identity генерирует новый идентификатор, который и запоминается в контексте вызова.

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

bool bTopLevel=false;

if (_property.SyncCallOutLCID==null) {

_property.SyncCallOutLCID = lcid;

bTopLevel = true;

}

Ну а теперь передаем исходящий вызов следующему перехватчику исходящих вызовов и ждем ответа

replyMsg = _nextSink.SyncProcessMessage(reqMsg);

Ну а теперь (после получения ответа) надо за собой почистить (если мы что-то поменяли в контексте вызова и в свойстве синхронизации):

if (bTopLevel) {

_property.SyncCallOutLCID = null;

if (bClear) {

LogicalCallContext cctxRet =

(LogicalCallContext)

replyMsg.Properties[Message.CallContextKey];

cctxRet.RemotingData.LogicalCalllD = null;

}

}

Здесь мы обнуляем свойство SyncCallOutLCID свойства синхронизации (если мы его только что сами установили) и обнуляем идентификатор для полученного ответа replyMsg (если мы сами задавали этот идентификатор для исходящего вызова).

Перехват исходящих асинхронных вызовов

Для обработки исходящих асинхронных вызовов перехватчик использует

следующий код:

public virtual IMessageCtrl AsyncProcessMessage(

IMessage reqMsg,

IMessageSink replySink) {

IMessageCtrl msgCtrl = null;

if (!_property.IsReEntrant) {

LogicalCallContext cctx =

(LogicalCallContext)

reqMsg.Properties[Message.CallContextKey];

String lcid = Identity.GetNewLogicalCalllD;

cctx.RemotingData.LogicalCalllD = lcid;

_property.AsyncCallOutLCIDList.Add(lcid);

}

AsyncReplySink mySink =

new AsyncReplySink(replySink, _property);

msgCtrl = _nextSink.AsyncProcessMessage (

reqMsg,

(IMessageSink)mySink);

return msgCtrl;

}

В качестве входных параметров задаются сам вызов reqMsg и перехватчик, на который вызывающая сторона ожидает получения уведомления о завершении процесса выполнения асинхронного вызова.

В случае нереентерабельного контекста исходящему асинхронному вызову назначается новый идентификатор и этот идентификатор сохраняется в списке _asyncLcidList исходящих асинхронных вызовов, поддерживаемому свойством синхронизации (доступ через свойство AsyncCallOutLCIDList). Заметим, что в случае асинхронных вызовов нет нужны сохранять один и тот же идентификатор по всей цепочке вызовов, в связи с чем здесь не проверяется наличие идентификатора, а сразу же назначается новый:

if (!_property.IsReEntrant) {

LogicalCallContext cctx =

(LogicalCallContext)

reqMsg.Properties[Message.CallContextKey];

String lcid = Identity.GetNewLogicalCallID;

cctx.RemotingData.LogicalCalllD = lcid;

_property.AsynCallOutLCIDList.Add(lcid);

}

Зачем вообще сохраняется список идентификаторов исходящих асинхронных вызовов? И почему он обновляется только для нереентерабельного случая?

Единственно, для чего этот список необходим (и именно в случае нереентерабельного контекста) — для определения того, является ли новый входящий вызов вложенным (см. код методов IsNestedCall и HandleWorkRequest). При изложении этого вопроса ранее уже отмечалось наличие некоторых проблем, связанных с определение понятия вложенного вызова и его использования.

Теперь пора отправить исходящий асинхронный вызов следующему перехватчику исходящих асинхронных вызовов. И тут мы должны указать, куда посылать уведомления о завершении вызова. Непосредственно использовать перехватчик уведомлений replySink, предоставленный вызывающей стороной, нельзя, т. к. его непосредственное использование может нарушить логику синхронизации, поддерживаемую в домене синхронизации. В связи с этим создается специальный перехватчик уведомлений mySink, который придерживается логики синхронизации и обеспечивает безопасную работу с replySink:

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

Барон нарушает правила

Ренгач Евгений
3. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон нарушает правила

Найди меня Шерхан

Тоцка Тала
3. Ямпольские-Демидовы
Любовные романы:
современные любовные романы
короткие любовные романы
7.70
рейтинг книги
Найди меня Шерхан

Отверженный VII: Долг

Опсокополос Алексис
7. Отверженный
Фантастика:
городское фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Отверженный VII: Долг

Искушение генерала драконов

Лунёва Мария
2. Генералы драконов
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Искушение генерала драконов

Собрание сочинений. Том 5

Энгельс Фридрих
5. Собрание сочинений Маркса и Энгельса
Научно-образовательная:
история
философия
политика
культурология
5.00
рейтинг книги
Собрание сочинений. Том 5

Лучше подавать холодным

Аберкромби Джо
4. Земной круг. Первый Закон
Фантастика:
фэнтези
8.45
рейтинг книги
Лучше подавать холодным

Лэрн. На улицах

Кронос Александр
1. Лэрн
Фантастика:
фэнтези
5.40
рейтинг книги
Лэрн. На улицах

От океана до степи

Стариков Антон
3. Игра в жизнь
Фантастика:
фэнтези
рпг
5.00
рейтинг книги
От океана до степи

Довлатов. Сонный лекарь 2

Голд Джон
2. Не вывожу
Фантастика:
альтернативная история
аниме
5.00
рейтинг книги
Довлатов. Сонный лекарь 2

Сирота

Шмаков Алексей Семенович
1. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Сирота

Я – Стрела. Трилогия

Суббота Светлана
Я - Стрела
Любовные романы:
любовно-фантастические романы
эро литература
6.82
рейтинг книги
Я – Стрела. Трилогия

Часовая битва

Щерба Наталья Васильевна
6. Часодеи
Детские:
детская фантастика
9.38
рейтинг книги
Часовая битва

Идеальный мир для Лекаря 26

Сапфир Олег
26. Лекарь
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 26

Барону наплевать на правила

Ренгач Евгений
7. Закон сильного
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Барону наплевать на правила