Вход/Регистрация
Интернет-журнал "Домашняя лаборатория", 2007 №6
вернуться

Журнал «Домашняя лаборатория»

Шрифт:

if (!IsNestedCall(work._reqMsg)) {……..

Правила обработки вложенного вызова зависят от реентерабельности контекста синхронизации. Если контекст реентерабельный, то никакой специальной обработки вложенных вызовов производить не надо. В этом случае любой новый вызов (в том числе и вложенный) имеет право исполняться в реентерабельном контексте в то время, как выполняемый в данный момент вызов приостановлен на время ожидания ответа на какой-либо сделанный в его рамках внешний вызов.

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

Рассмотрим определенный В ЭТОМ же классе SynchronizationAttribute метод IsNestedCall.

internal bool IsNestedCall(IMessage reqMsg) {

bool bNested = false;

if (!IsReEntrant) {

String lcid = SyncCallOutLCID;

if (lcid!= null) {

LogicalCallContext callCtx =

(LogicalCallContext)

reqMsg.Properties[Mes sage.CallContextKey];

if (callCtx!=null &&

lcid.Equals(callCtx.RemotingData.LogicalCalllD)) {

bNested = true;

}

}

if (IbNested && AsyncCallOutLCIDList.Count>0) {

LogicalCallContext callCtx =

(LogicalCallContext)

reqMsg.Properties[Message.CallContextKey];

if (AsyncCallOutLCIDList.Contains(

callCtx.RemotingData.LogicalCalllD)) {

bNested = true;

}

}

}

return bNested;

}

Этот метод возвращает true если текущий контекст (точнее, текущий домен синхронизации) нереентерабельный, а новый вызов (reqMsg) является вложенным для исполняемого в данный момент синхронного вызова, или для одного из исходящих асинхронных вызовов. Во всех остальных случаях возвращается false.

Вначале выясняется синхронность выполняемого в данный момент вызова:

String lcid = SyncCallOutLCID;

if (lcid!= null) {

......

}

Свойство SyncCallOutLCID атрибута синхронизации возвращает идентификатор логического вызова исполняемого в данный момент вызова, если этот вызов синхронный. В противном случае возвращается null.

Теперь в случае синхронности исполняемого вызова мы получаем доступ к контексту вызова для вызова reqMsg:

LogicalCallContext callCtx =

(LogicalCallContext)

reqMsg.Properties[Message.CallContextKey];

Надо заметить, что тут имеется ввиду класс Message из пространства имен System.Runtime.Remoting.Messaging. Реализация такого класса в этом пространстве имен имеется в Rotor, но отсутствует в .NET. Статическое поле CallContextKey равно __CallContext.

Если доступ к контексту вызова получен, то проверяется, что идентификатор логического вызова исполняемого в данный момент синхронного вызова lcid совпадает с идентификатором логического вызова для вызова reqMsg. В случае их совпадения флаг вложенности bNested получает значение true:

if (callCtx!=null &&

lcid.Equals(callCtx.RemotingData.LogicalCalllD)) {

bNested = true;

}

Здесь ОПЯТЬ приходится отметить, что в .NET у класса LogicalCallContext нет свойства RemotingData типа CallContextRemotingData, нет и самого класса CallContextRemotingData и его свойства LogicalCallID.

Если в данный момент не выполняется синхронный вызов, или новый вызов не является вложенным для исполняемого синхронного вызова, то начинается проверка вложенности нового вызова в один из исходящих асинхронных вызовов.

Выполнение условия AsyncCallOutLCIDList.count>0 означает, что список идентификаторов логических вызовов, соответствующих исходящим асинхронным вызовам, не пуст. Свойство AsyncCallOutLCIDList типа ArrayList возвращает ссылку на этот список.

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

LogicalCallContext callCtx =

(LogicalCallContext)

reqMsg.Properties[Message.CallContextKey];

if (AsyncCallOutLCIDList.Contains(

callCtx.RemotingData.LogicalCalllD)) {

bNested = true;

}

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

Здесь возможны два случая:

• IsNestedCall(work._reqMsg) == false

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

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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