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

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

Шрифт:

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

internal virtual void HandleWorkRequest(Workitem work) {

bool bQueued;

if (!IsNestedCall(work._reqMsg)) {

if (work.IsAsync) {

……

}

else {

lock(work) {

lock(_workltemQueue) {

if ((!_locked) &&

(_workltemQueue.Count == 0)) {

_locked = true;

bQueued = false;

}

else {

bQueued = true;

work.Setwaiting;

_workltemQueue.Enqueue(work);

}

}

if (bQueued == true) {

Monitor.Wait(work);

if (!work.IsDummy) {

……

}

else {

lock(_workltemQueue) {

_workItemQueue.Dequeue;

}

}

}

else {

if (!work.IsDummy) {

……

}

}

}

}

}

else {

……

}

}

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

Если домен был заблокирован, то фиктивная работа помечается как стоящая в очереди и записывается в очередь работ. Далее связанный с этой работой поток засыпает

Monitor.Wait(work);

и спит до тех пор, пока фиктивная работа не будет готова к выполнению, продвинувшись в очереди на первое место.

После пробуждения данного потока он выполняет код

if (!work.IsDummy) }

……

}

else {

lock(_workltemQueue) {

_workItemQueue.Dequeue;

}

}

Иными словами, фиктивная работа просто удаляется из очереди, после чего выполнение метода SyncProcessMessage завершается возвращением результата replyMsg и разбуженный поток продолжает выполнять основной вызов.

Случай нереентерабельного контекста

Теперь рассмотрим ветвь метода SyncProcessMessage класса SynchronizedClientContextSink, относящуюся к случаю нереентерабельного контекста:

public virtual IMessage SyncProcessMessage (

IMessage reqMsg) {

IMessage replyMsg;

if (_property.IsReEntrant) {

……

}

else {

LogicalCallContext cctx =

(LogicalCallContext)

reqMsg.Properties[Message.CallContextKey];

String lcid = cctx.RemotingData.LogicalCalllD;

bool bClear = false;

if (lcid == null) {

lcid = Identity.GetNewLogicalCalllD ;

cctx.RemotingData.LogicalCalllD = lcid;

bClear = 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;

}

}

}

return replyMsg;

}

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

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

LogicalCallContext cctx =

(LogicalCallContext)

reqMsg.Properties[Message.CallContextKey];

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

String lcid = cctx.RemotingData.LogicalCallID;

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

  • Читать дальше
  • 1
  • ...
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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