Шрифт:
Класс SynchronizedServerContextSinkсодержит два поля данных:
internal IMessageSink _nextSink;
internal SynchronizationAttribute _property;
Первое содержит ссылку на следующий перехватчик, а второе — на свойство синхронизации текущего домена синхронизации.
Единственный конструктор инициирует эти поля:
internal sSynchronizedServerContextSink (
SynchronizationAttribute prop,
IMessageSink nextSink) {
_property = prop;
_nextSink = nextSink
}
Каждый перехватчик должен обеспечить обработку как синхронных, так и асинхронных вызовов. Соответствующие методы объявлены в интерфейсе IMessageSink. Это SyncProcessMessage и AsyncProcessMessage.
В данном перехватчике обработка синхронных вызовов осуществляется следующим образом:
public virtual IMessage SyncProcessMessage(IMessage reqMsg) {
Workitem work = new Workitem(reqMsg,
_nextSink, null);
_property.HandleWorkRequest(work);
return work.ReplyMessage;
}
Собственно вызов в форме сообщения типа IMessage передается как единственный входной параметр. Возвращаемое значение (также типа IMessage) содержит результат, полученный данным перехватчиком от следующего в цепочки перехватчика после того, как вызов пройдет через всю цепочку перехватчиков до сервера, будет обработан на сервере, а ответ от него пройдет через всю цепочку перехватчиков в обратном направлении до данного перехватчика. Тут надо заметить, что на этом пути в каком-либо промежуточном перехватчике вызов может быть преобразован в асинхронную форму.
Роль данного перехватчика состоит в инкапсуляции вызова в объект типа WorkItem и его сохранении в очереди работ. Для этого вызывается конструктор WorkItem (reqMsg, _nextSink, null), первые два параметра которого задают вызов в форме сообщения и ссылку на следующий перехватчик. Третий параметр используется только в случае асинхронных вызовов. По умолчанию инкапсулирующая вызов работа work относится к синхронному типу.
После инкапсуляции вызова соответствующая работа передается свойству синхронизации:
_property.HandleWorkRequest(work);
Метод HandleWorkRequest класса SynchronizationAttribute ответственен за запись инкапсулированного вызова в очередь работ, за своевременное извлечение его из очереди и передачу следующему перехватчику, и, наконец, за получение ответа. Ответ доступен через свойство ReplyMessage работы, инкапсулирующей вызов. Значение этого свойства и возвращается как результат вызова метода SyncProcessMessage.
Как свойство синхронизации обрабатывает инкапсулированный синхронный вызов, полученный от перехватчика
Теперь временно прервем процесс изучение класса SynchronizedServerContextSink И рассмотрим метод HandleWorkRequest класса SynchronizationAttribute. Ниже приведена часть кода этого метода, которая относится к обработке именно синхронных вызовов:
internal virtual void HandleWorkRequest(WorkItem work) {
bool bQueued;
if (!IsNestedCall(work._reqMsg)) {
if (work.IsAsync) {
…….
}
else {
lock(work) {
lock(_workItemQueue) {
if ((!_locked) &&
(_workltemQueue.Count == 0)) {
_locked = true;
bQueued = false;
}
else {
bQueued = true;
work.SetWaiting;
_workltemQueue.Enqueue(work);
}
}
if (bQueued == true) {
Monitor.Wait(work);
if (!worк. IsDummy) {
DispatcherCallBack(null, true);
}
else {
lock(_workltemQueue) {
_workItemQueue.Dequeue;
}
}
}
else {
if (!worк. IsDummy) {
work.SetSignaled;
ExecuteWorkltem(work);
HandleWorkCompletion;
}
}
}
}
}
else {
work.SetSignaled;
work.Execute;
}
}
Прежде всего выясняется — является ли инкапсулированный вызов work._reqMsg вложенным вызовом, т. е. вызовом, инициированным в процессе выполнения выполняемого в данный момент синхронного или исходящего асинхронного вызова: