
После создания экземпляра test класса Test вызывается его метод 
NewEvent в результате чего из пула рабочих потоков извлекается новый поток, который и выполняет метод MyCallBack. 
Напомним, что после этого событие 
_myEvent автоматически переходит в начальное состояние.  
Далее основной поток засыпает на 500 mc. В связи с тем, что интервал ожидания, заданный четвертым параметром в  
ThreadPool.RegisterWaitForSingleObject равен 100 mc, метод MyCallBack будет вызван несколько раз по причине завершения 
периода ожидания.  
Далее во второй раз вызывается метод 
NewEvent, и MyCallBack вызывается по причине перехода события _myEvent в состояние 
signaled.  
И, наконец, основной поток засыпает еще на 1000 mc, в течении которых 
MyCallBack вызывается с интервалом 100 mc по 
причине завершения времени ожидания.  
Через 1000 mc основной поток просыпается и выполнение всего приложения (включая все рабочие потоки) завершается.  
Ниже приводится вывод на консоль, полученный после запуска данного приложения:  
>>> MyApp thread = 16 IsPoolThread = False 
>>> Test constructor thread = 16 IsPoolThread = False 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_1 :  Count = 1 timedOut = False 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_2 :  Count = 2 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_3 :  Count = 3 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_4 :  Count = 4 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_5 :  Count = 5 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_6 :  Count = 6 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_7 :  Count = 7 timedOut = False 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_8 :  Count = 8 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_9 :  Count = 9 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_10 :  Count = 10 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_11 :  Count = 11 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_12 :  Count = 12 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_13 :  Count = 13 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_14 :  Count = 14 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_15 :  Count = 15 timedOut = True 
>>> MyCallback thread = 18 IsPoolThread = True 
Test_16 :  Count = 16 timedOut = True 
Возвращаемся к коду инициализации атрибута  
Теперь можно более подробно обсудить код метода InitIfNecessary. Все тело этого метода включено в критическую секцию 
lock(this) {}. Здесь this является ссылкой на экземпляр текущего класса  
(
SynchronizationAttribute), который и является собственно свойством синхронизации (как контекста, так и домена 
синхронизации). Таким образом, при входе текущего потока в данную критическую секцию никакой другой поток не может 
войти в эту секцию (и в любую другую типа 
lock(obj) {}, где obj является ссылкой на данное свойство синхронизации).  
Далее проверяется условие 
_asyncWorkEvent == null. Это условие выполняется только тогда, когда текущее свойство 
синхронизации еще не инициализовано, т.е. в данный момент формируется новый домен синхронизации и текущее свойство 
будет его свойством синхронизации. Именно в этом случае выполняется инициализация свойства. В противном случае код 
инициализации пропускается, т.к. текущее свойство уже инициализированно ранее.  
Инициализация состоит 
из следующих шагов:  
z Создается экземпляр _asyncWorkEvent события AutoResetEvent  
Данное событие будет использовано для уведомления системы о том, что очередной рабочий поток из пула потоков может 
выполнить очередной вызов, сохраненный в очереди вызовов (см. следующий пункт). Начальное состояние данного 
события не равно signaled, и для уведомления системы это событие надо перевести в состояние signaled (после чего оно 
автоматически вернется в исходное 
состояние).  
z Создается экземпляр _workItemQueue очереди Queue  
Поддержание этой очереди - основная задача свойства синхронизации. Как правило, внешние вызовы, приходящие к 
объектам некоторого домена синхронизации, преобразуются в специальную форму - так называемую работу, и сохраняются 
в данной очереди (в некоторых случаях вызов не сохраняется в очереди и выполняется сразу же). Очередная работа 
извлекается из этой очереди и выполняется при 
готовности системы выполнять новую работу.  
z Создается список _asyncLcidList  
Данный список будет использоваться для хранения идентификаторов логических вызовов для асинхронных вызовов, 
исходящих из данного домена синхронизации. Подробнее это будет обсуждаться далее.