И Чтобы понять, как с помощью атрибутов среда времени выполнения реализует требования организации поточной обработки, мы должны ввести понятие контекста. Шаг 4 из примера Threading (Организация поточной обработки) состоит из того же кода, что и шаг 3, но в выдаче есть дополнительная информация:
Is the customer object a proxy? False
Is the bookings object a proxy? True
Added Boston Presidential Hotel with one room.
Thread 13 Contextld 0 launching threads.
MakeReservation: Thread 28 Contextld 0 starting.
MakeReservation: Thread 29 Contextld 0 starting.
Reserving for Customer 2 at the Boston Presidential Hotel on
12/13/2001 12:00:00
Перевод такой:
Объект Клиент является агентом? Ложь
Заказывающий объект является агентом? Истина
Добавлена Бостонская Президентская гостиница с одним номером.
Поток 13 Contextld 0 запускает потоки.
MakeReservation: Поток 28 Contextld 0 стартовал.
MakeReservation: Поток 29 Contextld 0 стартовал.
Резервирование для Клиента 2 в Бостонской Президентской гостинице
на
12/13/2001 12:00:00
AM в течение 1 дня
Поток 29 Contextld 1 вошел в Резерв.
Поток 29 находит, что номер доступен в Брокер::Резерв
Резервирование для Клиента 1 в Бостонской Президентской гостинице
на
12/12/2001 12:00:00
AM в течение 3 дней
Поток 29 Contextld 1 вышел из Резерва.
Поток 28 Contextld 1 вошел в Резерв.
Поток 28 Contextld 1 вышел из Резерва.
Резервирование для Клиента 1 не могло быть заказано
Номер не доступен
Резервирование для Клиента 2 было заказано
Reservationld = 1
ReservationRate = 10000
ReservationCost = 10000
Комментарий = OK
На этом последнем шаге (шаг 4) примера Threading (Организация поточной обработки) мы видим, что во время выполнения метода класса Broker (Брокер), такого как Reserve (Резерв), поток имеет идентификатор контекста Contextld, который отличается от идентификатора контекста во время выполнения какого-нибудь метода вне класса. Поток выполняется в различных контекстах. Это объясняет, почему в вышеприведенной распечатке поток 28, у которого идентификатор контекста Contextld был равен О перед вызовом метода Reserve (Резерв), изменяет свой идентификатор контекста Contextld на 1 во время выполнения данного метода. Такое поведение обусловлено применением атрибута Synchronization (Синхронизация) к классу Broker (Брокер).
Объекты класса Broker (Брокер) имеют отличные от других объектов требования во время выполнения. Поэтому доступ к объектам Broker (Брокер) должен быть синхронизирован, а доступ к другим объектам — нет. Среда, которая реализует требования какого-либо объекта во время выполнения, называется контекстом. В примере Threading (Организация поточной обработки) на шаге 3 и шаге 4 реализуются два контекста: контекст 1, в котором живет объект Broker (Брокер) и контекст 0, в котором сосуществуют все другие объекты. Каждый поток в программе будет выполняться либо в контексте 1 во время выполнения методов объекта класса Broker (Брокер), либо в контексте 0 в остальных случаях. Контекст не зависит от выполняющихся в нем потоков.
Контекст — совокупность одного или более объектов с идентичными требованиями
параллелизма. Концепция контекста в .NET подобна концепции апартаментов (apartment)
модели компонентных объектов Microsoft (COM) и концепции контекста в СОМ+. Вообще
нельзя предсказать, что нужно делать во время выполнения в рамках заданного
контекста. Это зависит от требований, предъявляемых во время выполнения. Контекст
с требованиями, касающимися проведения транзакций, диктует иные действия, чем
контекст, к которому такие требования не предъявляются. Или, если контекст поддерживает
атрибут REQUIRED (ТРЕБУЕМЫЙ) в требованиях к синхронизации, то он отличается
от контекста, поддерживающего в требованиях к синхронизации атрибут REQUIRES_NEW.
Экземпляр класса Context (Контекст), который представляет текущий контекст,
можно получить с помощью статического свойства Thread: :CurrentContext. Context
Id — это свойство класса Context (Контекст).