В начале программирования в СОМ большинство людей мало знает (или не знают вообще) о моделях потоков и окружений в СОМ. Не набравшись опыта, они не понимают, что за модель свободных потоков приходится расплачиваться значительным снижением производительности, когда клиентский поток в
однопоточном окружении
(single-threaded apartment, STA) используется для создания объекта в
многопоточном окружении
(multithreaded apartment, MTA). Кроме того, начинающие программисты в СОМ часто не знают о безопасности потоков и о том, чем им угрожает одновременное обращение нескольких потоков к их компонентам СОМ.
Прежде чем вызвать объект СОМ, поток должен объявить свою принадлежность к определенному окружению, указывая, что он может входить в
STA
или
МТА.
Клиентские потоки
STA
вызывают
Colnitiali-ze(NULL)
или
Со Initialize Ex(О, COINIT_APARTMENTTHREADED),
чтобы войти в
STA,
а потоки
МТА
вызывают
Со Initialize Ех(О, COINIT_MULTI-THREADED)
для входа в
МТА.
Сходным образом в мире .NET у вас есть выбор: вы можете позволить вызывающему потоку в управляемом пространстве объявить свою принадлежность к некоторому окружению. Вызывающий поток в управляемом приложении выбирает
МТА
как свое место обитания по умолчанию. Это аналогично тому, как если бы вызывающий поток инициализировался с параметрами
CoInitializeEx(0, COINIT_MULTITHREADED).
Но подумайте об издержках и потерях производительности, которые будут иметь место, если вызывающим потоком будет классический СОМ-компонент
STA,
разработанный для отдельного потока многопоточного процесса. Несовместимые окружения также приведут к издержкам в связи с дополнительными парами "про-кси/заглушка", за что определенно придется расплачиваться производительностью.
В связи с этим вы можете изменить выбор окружения по умолчанию для управляемого потока в приложении .NET с помощью свойства Apart-mentState класса System. Threading. Thread. Свойство ApartmentState принимает одно из значений:
До осуществления любых вызовов объекта СОМ вам также нужно задать свойство
ApartmentState
для вызывающего потока. Заметьте: после создания объекта СОМ изменить свойство
ApartmentState
нельзя. Поэтому имеет смысл установить свойство потока
ApartmentState
в программе как можно раньше. Вот как это сделать:
// Установить свойство клиентского потока ApartmentState для входа в STA.
Thread.CurrentThread.ApartmentState = ApartmentState.STA;
// Создать объект COM посредством Interop. MySTA obj STA = new MySTAQ; objSTA.MyMethodQ