Шрифт:
}
……
}
……
public class Tax: ContextBoundObject {
……
private SynchronizationAttribute _syncProperty;
public Tax {
…….
_syncProperty =
(SynchronizationAttribute)
Thread.CurrentContext.GetProperty {
"Synchronization");
……
}
…….
internal SynchronizationAttribute syncProperty {
get { return _syncProperty;}
}
……
}
…….
Просматривая консоль сервера убеждаемся, что ссылки на свойство синхронизации в обоих контекстах (в контексте, в котором живет компонент Account и в контексте, в котором живут компоненты Tax и News) указывают на один объект — свойство синхронизации домена синхронизации:
Server is listening
News context = 2 News constructor thread = 9 IsPoolThread = True
Tax context = 2 Tax constructor thread = 9 IsPoolThread = True
Account context = 1 Account constructor thread = 9 IsPoolThread = True
Account syncProperty == Tax syncProperty True
…….
Компоненты размещаются в трех контекстах и в двух доменах синхронизации
Заменим атрибут синхронизации, приписанный компоненту News следующей его версией:
[Synchronization(0x00000008)]
Задание данного атрибута означает, что компонент News будет располагаться в новом контексте (3), причем этот контекст образует и новый домен синхронизации. Компоненты Account и Tax должны располагаться в различных контекстах (1 и 2), но эти контексты должны входить в один домен синхронизации.
Для проверки этих утверждений внесем еще несколько дополнений в код сервера:
…….
namespace SPbU.AOP_NET {
……
public class Tax: ContextBoundObject {
…….
public Tax {
…….
Console.WriteLine {
"Tax syncProperty == News syncProperty "+
Object.ReferenceEquals(_syncProperty,
_news.syncProperty));
……
}
…….
}
…….
public class News: ContextBoundObject {
private SynchronizationAttribute _syncProperty;
public News {
_syncProperty =
(SynchronizationAttribute)
Thread.CurrentContext.GetProperty {
"Synchronization");
……
}
……
internal SynchronizationAttribute syncProperty {
get { return _syncProperty;}
}
…….
}
Просматривая консоль сервера убеждаемся в том, что компонент News размещается в новом домене синхронизации:
Server is listening
News context = 3 News constructor thread = 9 IsPoolThread = True
Tax syncProperty == News syncProperty False
Tax context = 2 Tax constructor thread = 9 IsPoolThread = True
Account context = 1 Account constructor thread = 9 IsPoolThread = True
Account syncProperty == Tax syncProperty True
…….
И последнее замечание касается файла LogFile. Просматривая его, можно заметить, что теперь перехватываются все вызовы, идущие к компонентам Tах и News, идущие не только от компонента Account, но и от компонента Tах к компоненту News. Это объясняется тем, что все компоненты живут в различных контекстах и все вызовы пересекают границу контекста и, следовательно, перехватываются.
Еще раз про атрибут синхронизации
Эта глава продолжает изучение кода атрибута синхронизации из Rotor, рассмотрение которого было начато в предыдущей главе. Там мы рассмотрели основные механизмы, связанные с определением контекста и домена синхронизации, в которых будет размещен новый объект — экземпляр класса, которому приписан атрибут SynchronizationAttribute. Это конструкторы (четыре варианта) и методы IsContextOK и GetPropertiesForNewContext класса SynchronizationAttribute. Теперь мы сосредоточимся на самом алгоритме синхронизации и попутно рассмотрим несколько важных понятий, связанных с программированием в CLR.
Инициализация свойства синхронизации в домене синхронизации
Начнем с метода InitIfNecessary класса SynchronizationAttribute:
internal virtual void InitlfNecessary {
lock(this) {
if (_asyncWorkEvent == null) {
_asyncWorkEvent = new AutoResetEvent(false);
_workltemQueue = new Queue;
_asyncLcidList = new ArrayList;
WaitOrTimerCallback callBackDelegate =