Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Материалы к лекциям COM.doc
Скачиваний:
4
Добавлен:
18.04.2019
Размер:
880.64 Кб
Скачать

9.2. Однопоточные и многопоточные апартаменты (sta и mta)

9.2.1. Однопоточные апартаменты (sta)

Однопоточный апартамент (STA) – это апартамент, содержащий только один поток. COM синхронизирует все обращения к методам COM-объекта, находящегося в STA. Делается это через очередь сообщений Windows. Каждый поток клиентского процесса или внепроцессного (EXE) сервера, желающий работать в отдельном апартаменте, должен вызвать CoInitialize или CoInitializeEx с параметром dwCoInit, равным COINIT_APARTMENTTHREADED (эти вызовы и приводят к инициализации потока и выделению ему синхронизирующей очереди сообщений). Внутрипроцессные объекты, располагающиеся в DLL (в том числе COM+/MTS-объекты), регистрируют свою поточную модель в реестре с помощью именованного значения ThreadingModel внутри ключа InprocServer32. При передаче указателей на интерфейсы между разными STA, или между STA и MTA, должен обязательно производиться маршаллинг. При передаче указателя на интерфейс как параметра метода какого-нибудь интерфейса, или при создании нового COM-объекта, маршаллинг делается автоматически. Если необходимо вручную (без использования COM, например, через общую область памяти) передать указатель на интерфейс другому потоку, необходимо произвести «ручной» маршаллинг.

Для «ручного» маршаллинга используется функция CoMarshalInterThreadInterfaceInStream (эта функция – рекордсмен среди Win32 API-функций по длине имени). В качестве первого параметра ей передается IID интерфейса. В качестве второго – указатель на этот интерфейс. В качестве третьего – указатель на интерфейс IStream, в который и будет записана информация о передаваемом интерфейсе. Перед вызовом этой функции необходимо создать объект, реализующий интерфейс IStream. Самый простой способ сделать это – воспользоваться API-функцией CreateStreamOnHGlobal, создающей Stream, базирующийся на оперативной памяти. Последнее, что необходимо сделать – это из другого потока выполнить обратный маршаллинг. Для этого необходимо вызвать CoGetInterfaceAndReleaseStream. Ручной маршаллинг очень редко применяется на практике. Если же возникнет необходимость делать его часто, то можно создать простой класс-обертку, или воспользоваться глобальной (для процесса) таблицей интерфейсов. Она похожа на AOM (Active Object Map) в Corba. Управление глобальной таблицей интерфейсов производится через стандартный интерфейс IGlobalInterfaceTable. Указатель на него можно получить, создав COM-объект с CLSID CLSID_StdGlobalInterfaceTable. Еще один способ избавиться от «ручного маршалинга» – агрегировать специальный объект FreeThreadedMarshaler. Для создания такого объекта используется функция CoCreateFreeThreadedMarshaler. ATL Wizard позволяет автоматизировать всю работу по созданию и агрегированию ThreadedMarshaler.

При использовании STA нет необходимости в ручной синхронизации, ведь все вызовы и так происходят строго последовательно.

Процесс может содержать любое количество STA.

9.2.2. Многопоточный апартамент (mta)

Многопоточный апартамент (MTA) – это апартамент, содержащий несколько потоков. MTA еще называют свободно-поточным. Маршаллинг указателей на интерфейсы в MTA-апартаменте не производится, а любой компонент может получать вызовы своего метода из любого другого потока, входящего в этот же MTA. При этом вызовы методов компонента могут осуществляться параллельно. Параллелизм многопоточных объектов обеспечивает высочайшую производительность и полностью использует преимущества многопроцессорного аппаратного обеспечения. Он позволяет пользователям работать, не дожидаясь окончания длительных операций, выполняемых другими пользователями. Однако синхронизация, и вообще все, что связано с потокобезопасностью, возлагается на код вызываемого компонента. Для синхронизации при этом можно использовать стандартные средства Windows (Мьютексы, Семафоры, События и, конечно, оконные очереди). Создание корректно работающего многопоточного ПО – задача не из простых. Многопоточная отладка, пожалуй, самая неудобная сторона современного программирования, но получаемые преимущества зачастую перевешивают трудности.

Процесс может содержать только один MTA.