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

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

Жанры

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

Далее сохраняется текущий контекст вызова в оldCаllСontехt, а с текущим потоком связывается тот контекст вызова, который был сохранен в поле _сallContext:

LogicalCallContext oldCallCtx =

CallContext.SetLogicalCallContext(_callCtx);

К сожалениею, в сигнатуре класса CallContext в .NET Framework нет метода SetLogicalCallContext.

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

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

Интерфейс IMessageSink объявляет два метода, реализующие обработку соответственно синхронных и асинхронных вызовов. Это SyncProcessMessage И AsyncProcessMessage.

Таким образом, в зависимости от типа текущей работы (инкапсулированного в ней вызова), необходимо вызвать один из упомянутых вызовов на следующем перехватчике:

if (IsAsync) {

_nextSink.AsyncProcessMessage(_reqMsg, _replySink);

}

else if (_nextSink!= null) {

_replyMsg = _nextSink.SyncProcessMessage(_reqMsg);

}

Вызов IsAsync возвращает true если текущая работа асинхронна. В этом случае на следующем перехватчике _nextSink вызывается AsyncProcessMessage и в качестве параметров передаются исходный вызов _reqMsg и ссылка на перехватчик для возвращения результата _replySink.

В случае синхронной работы вызывается SyncProcessMessage. Параметром является вызов, возвращаемое значение сохраняется в поле replyMsg.

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

И, наконец, текущий поток должен вернуться в старый контекст и связаться со старым контекстом вызова:

CallContext.SetLogicalCallContext(oldCallCtx);

Thread.CurrentThread.ReturnToContext(ref frame);

Завершая обсуждение класса WorkItem осталось упомянуть свойство ReplyMessage, с помощью которого можно получить ответ, возвращенный для синхронного вызова:

internal virtual IMessage ReplyMessage {

get {return _replyMsg;}

}

Извлечение работы из очереди и ее выполнение

Напомним, что вызовы, перехваченные перехватчиком, ассоциированным со свойством синхронизации, инкапсулируются в работу (экземпляр класса WorkItem) и записываются в очередь работ (_workItemQueue). Эта очередь поддерживается свойством синхронизации, и мы уже говорили об ее инициализации как составной части процесса инициализации свойства синхронизации в целом. Тогда же говорилось о том, что в пуле рабочих потоков регистрируется делегат callBackDelegate типа WaitOrTimerCallBack, который будет вызываться и выполняться некоторым рабочим потоком всякий раз, когда будет установлено в состояние signaled событие _asyncWorkEvent.

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

Делегат callBackDelegate содержит ссылку на функцию

DispatcherCallBack:

WaitOrTimerCallback callBackDelegate =

new WaitOrTimerCallback(this.DispatcherCallBack);

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

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

Код функции DispatcherCallBack представлен ниже:

private void DispatcherCallBack(Object statelgnored,

bool ignored) {

Workltem work;

lock (_workItemQueue) {

work = (Workltem) _workltemQueue.Dequeue;

}

ExecuteWorkltem(work);

HandleWorkCompletion;

}

В соответствии с определением типа WaitorTimerCallBack функция DispatcherCallBack имеет два параметра. Входной параметр типа Object (третий параметр при вызове ThreadPool.RegisterWaitForSingleObject. В нашем случае null) используется для задания подлежащей обработке информации. Выходной параметр типа bool принимает значение true в том случае, если вызов зарегистрированного в пуле рабочих потоков соответствующего делегата (в нашем случае callBackDelegate) произошел по причине истечения времени ожидания (в нашем случае это значение поля _timeOut). Если же вызов упомянутого делегата произошел в связи с тем, что зарегистрированное в этом же пуле событие типа AutoResetEvent (в нашем случае _asyncWorkEvent) перешло в состояние signaled, то второй параметр принимает значение false. В нашем случае оба эти параметра не учитываются.

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

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

После выхода из критической секции (освобождающего очередь работ для других потоков), вызываются последовательно ExecuteWorkltem(work) и HandleWorkCompletion .

Реализация метода ExecuteWorkItem в рассматриваемом классе SynchronizationAttribute Очень проста:

internal void ExecuteWorkltem(Workitem work) {

work.Execute;

}

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

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

Ваантан

Кораблев Родион
10. Другая сторона
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Ваантан

Моя (не) на одну ночь. Бесконтрактная любовь

Тоцка Тала
4. Шикарные Аверины
Любовные романы:
современные любовные романы
7.70
рейтинг книги
Моя (не) на одну ночь. Бесконтрактная любовь

Изгой. Пенталогия

Михайлов Дем Алексеевич
Изгой
Фантастика:
фэнтези
9.01
рейтинг книги
Изгой. Пенталогия

Приручитель женщин-монстров. Том 4

Дорничев Дмитрий
4. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 4

На границе империй. Том 5

INDIGO
5. Фортуна дама переменчивая
Фантастика:
боевая фантастика
попаданцы
7.50
рейтинг книги
На границе империй. Том 5

Проклятый Лекарь IV

Скабер Артемий
4. Каратель
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Проклятый Лекарь IV

Измена. Мой заклятый дракон

Марлин Юлия
Любовные романы:
любовно-фантастические романы
7.50
рейтинг книги
Измена. Мой заклятый дракон

Варлорд

Астахов Евгений Евгеньевич
3. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Варлорд

Отмороженный 5.0

Гарцевич Евгений Александрович
5. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный 5.0

Вернуть невесту. Ловушка для попаданки

Ардова Алиса
1. Вернуть невесту
Любовные романы:
любовно-фантастические романы
8.49
рейтинг книги
Вернуть невесту. Ловушка для попаданки

Пятое правило дворянина

Герда Александр
5. Истинный дворянин
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Пятое правило дворянина

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

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

Опер. Девочка на спор

Бигси Анна
5. Опасная работа
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Опер. Девочка на спор

Лорд Системы

Токсик Саша
1. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
4.00
рейтинг книги
Лорд Системы