
аботу (экземпляр класса WorkItem) и записываются в очередь работ (_workItemQueue). Эта очередь поддерживается свойством 
синхронизации, и мы уже говорили об ее инициализации как составной части процесса инициализации свойства синхронизации в 
целом. Тогда же говорилось о том, что в пуле рабочих потоков регистрируется делегат callBackDelegate типа 
WaitOrTimerCallBack, который будет вызываться и выполняться некоторым рабочим потоком всякий раз, когда будет 
установлено в состояние signaled событие 
_asyncWorkEvent.  
Забегая вперед можно сказать, что это событие будет устанавливаться в состояние signaled всякий раз, когда можно будет 
начинать выполнение очередной работы из очереди работ, причем эта работа должна имееть асинхронный тип (инкапсулирует 
асинхронный вызов). В этом случае свободный или вновь сгенерированный рабочий поток начнет выполнять данную 
асинхронную работу путем вызова упомянутого 
делегата.  
Делегат 
callBackDelegate содержит ссылку на функцию  
DispatcherCallBack :  
  WaitOrTimerCallback callBackDelegate =  
                new WaitOrTimerCallback(this.DispatcherCallBack); 
и именно эта функция будет выполняться в рабочем потоке, обрабатывая очередную асинхронную работу. 
Кстати, эта же функция будет вызываться и в том случае, когда очередная работа имеет синхронный тип (инкапсулирует 
синхронный вызов). Правда, в этом случае она будет выполняться в потоке вызова, а не в произвольном рабочем потоке из пула 
потоков
, как было при асинхронном вызове. Но об этом позже.  
Код функции 
DispatcherCallBack представлен ниже:  
    private void DispatcherCallBack(Object stateIgnored,  
        bool ignored) { 
         
        WorkItem work;      
         
        lock (_workItemQueue) { 
            work = (WorkItem) _workItemQueue.Dequeue(); 
        } 
             
        ExecuteWorkItem(work); 
        HandleWorkCompletion(); 
    } 
В соответствии с определением типа WaitOrTimerCallBack функция  
DispatcherCallBack имеет два параметра. Входной параметр типа Object (третий параметр при вызове 
ThreadPool.RegisterWaitForSingleObject, в нашем случае null) используется для задания подлежащей обработке 
информации. Выходной параметр типа 
bool принимает значение true в том случае, если вызов зарегистрированного в пуле 
рабочих потоков соответствующего делегата (в нашем случае 
callBackDelegate) произошел по причине истечения времени 
ожидания (в нашем случае это значение поля 
_timeOut). Если же вызов упомянутого делегата произошел в связи с тем, что 
зарегистрированное в этом же пуле событие типа 
AutoResetEvent (в нашем случае _asyncWorkEvent) перешло в состояние 
signaled, то второй параметр принимает значение 
false. В нашем случае оба эти параметра не учитываются.  
Выполнение вызова DispatcherCallBack начинается с входа в критическую секцию, доступную при успешной блокировке 
объекта 
_workItemQueue. В результате, при работе в данной критической секции с очередью работ, поддерживаемой текущим 
свойством синхронизации, никакой другой код не сможет заблокировать эту очередь и параллельно начать с ней работать.  
Единственной операцией, выполняемой в данной критической секции, является извлечение из очереди работ очередной работы (с 
удалением из очереди). Здесь предполагается, что 
все необходимые для этого условия уже выполнены. О том, каковы эти 
условия, мы будем говорить позже.  
После выхода из критической секции (освобождающего очередь работ для других потоков), вызываются последовательно 
ExecuteWorkItem(work) и HandleWorkCompletion().  
Реализация метода 
ExecuteWorkItem в рассматриваемом классе  
SynchronizationAttribute очень проста:  
    internal void ExecuteWorkItem(WorkItem work) { 
        work.Execute(); 
    } 
Тут все сводится к уже рассмотренному методу Execute класса WorkItem. Иными словами, исполняющий этот метод поток 
переходит в тот контекст, где должен будет выполняться вызов, с этим потоком связывается тот самый контекст вызова, который 
сопровождал этот вызов до его перехвата. После этого вызов передается следующему перехватчику, который будет его 
обрабатывать в зависимости от типа вызова (синхронный или асинхронный). В случае 
асинхронного вызова сразу же после этого 
происходит возврат потока в исходный контекст и восстанавливается его связь с исходным контекстом вызова. В случае 
синхронного вызова происходит тоже самое, но только после возврата ответа.  
Вызов метода 
HandleWorkCompletion() должен выполнить некоторую подготовительную работу к выполнению следующей 
работы из очереди работ. Мы рассмотрим этот метод позже. Сейчас же следует начать с начала, т.е. рассмотреть весь процесс 
перехвата вызова и включения его в очередь (или, в некоторых случаях, исполнения без включения в очередь).  
Перехват входящего вызова