ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
Шрифт:
Замечание. В этой книге не рассматриваются подробности создания пользовательских контекстов объектов, но если вы заинтересованы узнать об этом больше, прочитайте книгу Applied .NET Attributes (Apress, 2003).
Определение контекстно-связанных объектов
Чтобы определить класс (SportsCarTS), автоматически поддерживающий потоковую безопасность, без добавления в него сложной логики синхронизации патока при реализации членов, следует взять объект, производный от ContextBoundObject, и применить атрибут [Synchronization], как показано ниже.
Типы с атрибутом [Synchronization] загружаются в контексте сохранения потоков. С учетом специальных контекстуальных требований типа класса MyThreadSafeObject представьте себе те проблемы, которые должны возникнуть, если размещенный объект перевести из синхронизированного контекста в несинхронизированный. Объект вдруг перестанет быть защищенным в отношении потоков и превратится в потенциального нарушителя целостности данных, поскольку другие потоки могут пытаться взаимодействовать с этим ссылочным объектом (теперь уже не сохраняющим потоки). Для гарантии того, что среда CLR не переместит объекты SportsCarTS за рамки синхронизированного контекста, достаточно взять объект, производный от ContextBoundObject.
Проверка контекста объекта
Из тех приложений, которые вы построите сами, очень немногие могут потребовать программного взаимодействия с контекстом, но вот вам пример для иллюстрации подхода, о котором идет речь. Создайте новое консольное приложение с именем ContextManipulator. Это приложение будет определить один контекстно-независимый класс (SportsCar) и один контекстно-связанный (SportsCarTS).
Обратите внимание на то. что каждый конструктор получает тип Context от текущего потока выполнения через статическое свойство Thread.CurrentContext. Используя объект Context, вы можете распечатать информацию о границах контекста, например, значение ID контекста или значения дескрипторов, полученных через Context.ContextProperties. Это свойство возвращает объект, реализующий интерфейс IContextProperty, который обеспечивает доступ к дескрипторам с помощью свойства Name. Теперь обновите метод Main, чтобы разместить по экземпляру каждого из типов класса.
По мере создания объектов конструкторы классов отображают различные элементы информации о контексте (рис. 13.10).
Рис. 13.10. Исследование контекста объекта
Для класса SportsCar не был указан атрибут контекста, поэтому среда CLR размещает sport и sport2 в контексте 0 (т.е. в контексте, созданном по умолчанию). Однако объект SportsCarTS загружается в свои уникальные контекстуальные границы (которым назначается идентификатор 1), поскольку для этого контекстно-связанного типа был указан атрибут [Synchronization].
Исходный код. Проект ContextManipulator размещен в подкаталоге, соответствующем главе 13.
Еще несколько слов о процессах, доменах приложения и контекстах
К этому моменту вы должны лучше понимать, как среда CLR обрабатывает компоновочные блоки .NET. Вот на что следует обратить внимание.
• Процесс .NET может содержать один или несколько доменов приложения. Каждый домен приложения может принять любое число связанных компоновочных блоков .NET и независимо загружаться и выгружаться средой CLR (или программистом с помощью типа System.AppDomain).
• Любой домен приложения состоит из одного или нескольких контекстов. Используя контексты, среда CLR может поместить объект со "специальными требованиями" в логический контейнер, чтобы гарантировать выполнение этих требований в среде выполнения.
Если предыдущее обсуждение кажется вам слишком сложным и далеким от практики, не волнуйтесь. По большей части среда выполнения .NET автоматически разрешает вопросы процессов, доменов приложений и контекстов, не требуя вашего вмешательства. Тем не менее представленная здесь информация обеспечивает "твердую основу" для понимания принципов многопоточного программирования в рамках платформы .NET. Но перед тем, как перейти к изучению пространства имен System.Threading, мы попытаемся выяснить, как сама среда CLR обрабатывается операционной системой Win32.