Шрифт:
>>> 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. Это условие выполняется только тогда, когда текущее свойство синхронизации еще не инициализовано, т. е. в данный момент формируется новый домен синхронизации и текущее свойство будет его свойством синхронизации. Именно в этом случае выполняется инициализация свойства. В противном случае код инициализации пропускается, т. к. текущее свойство уже инициализирование ранее.
Инициализация состоит из следующих шагов:
• Создается экземпляр _asyncWorkEvent события AutoResetEvent
Данное событие будет использовано для уведомления системы о том, что очередной рабочий поток из пула потоков может выполнить очередной вызов, сохраненный в очереди вызовов (см. следующий пункт). Начальное состояние данного события не равно signaled, и для уведомления системы это событие надо перевести в состояние signaled (после чего оно автоматически вернется в исходное состояние).
• Создается экземпляр _workItemQueue очереди Queue
Поддержание этой очереди — основная задача свойства синхронизации. Как правило, внешние вызовы, приходящие к объектам некоторого домена синхронизации, преобразуются в специальную форму — так называемую работу, и сохраняются в данной очереди (в некоторых случаях вызов не сохраняется в очереди и выполняется сразу же). Очередная работа извлекается из этой очереди и выполняется при готовности системы выполнять новую работу.
• Создается список _asyncLcidList
Данный список будет использоваться для хранения идентификаторов логических вызовов для асинхронных вызовов, исходящих из данного домена синхронизации. Подробнее это будет обсуждаться далее.
• Создается делегат callBackDelegate типа WaitOrTimerCallBack
Этот делегат хранит ссылку на функцию DispatcherCallBack, которая и будет обрабатывать вызовы, извлекаемые из очереди вызовов.
• Регистрация делегата callBackDelegate и события _asyncWorkEvent в пуле рабочих потоков
Для регистрации используется статический метод RegisterWaitForsingieObject класса ThreadPool. Третий параметр в вызове данного метода равен null, что говорит о том, что функции DispatcherCallBack не передаются никакие данные. Величина интервала ожидания timeout, по истечении которого автоматически вызывается делегат (если ранее состояние _asyncWorkEvent не было переведено в состояние signaled), задается при инициализации атрибута синхронизации и доступна только для чтения: