STA или MTA для косвенно используемых COM-объектов
Я думаю, что понимаю концепцию квартиры и почему используется STA или MTA, однако возник вопрос, для которого я до сих пор не нашел решения.
Если мое приложение использует COM-объекты, например, из сторонних библиотек, как мне узнать, могу ли я использовать MultiThreaded-Appartment (MTA)? В этом случае у меня нет идеи, если эти объекты являются потокобезопасными, так что мне нужно идти с STA, просто чтобы быть в безопасности?
2 ответа
Ваша способность использовать определенный указатель COM-интерфейса в коде потока STA или MTA зависит от того, получили ли вы вообще указатель на этот поток. Если вы можете получить точку в потоке STA (или MTA) - вы можете использовать ее дальше, при условии, что вы не передадите ее напрямую в другую квартиру.
Если COM-сервер зарегистрирован определенным образом, и вы не можете получить указатель из-за несоответствия типа квартиры (типичный случай: STA-поток и COM-сервер зарегистрированы с использованием "свободной" модели квартиры), тогда COM попытается маршалировать указатель за вас. Если маршалинг успешен, ваш код получает указатель, и вы можете идти оттуда. В противном случае вы получите ошибку, и ваша попытка сделать то же самое из другой квартиры будет успешной. По сути, это единственный надежный универсальный метод, позволяющий получить ответ о возможности использования определенного интерфейса COM в потоке STA или MTA.
В более конкретном случае создания экземпляра COM-объекта вы можете просмотреть информацию о его реестре, чтобы определить, соответствует ли экземпляр вашему типу квартиры. Внешние серверы в любом случае предоставят вам указатели COM-интерфейса посредством маршалинга, поэтому любая клиентская квартира сможет использовать этот сервер.
Нет вопроса о том, являются ли объекты сервера потокобезопасными. Если их регистрация COM верна (особенно если сервер STA in-proc не объявляет о бесплатной / обеих регистрациях) и маршалинг доступен, безопасность потоков включается бесплатно.
Зарегистрированные COM-объекты будут принадлежать квартире в соответствии с полем ThreadingModel (есть еще одна статья о COM-квартирах с большим, возможно, более простым столом).
По сути, ThreadingModel сообщает, к какой квартире будет принадлежать вновь созданный объект:
Не указан
Главный СТА (первый
CoInitialize
d STA; если его не существует, COM создает его, который называется STA хоста)квартира
STA (если мы находимся в STA, так и будет, в противном случае - STA хоста)
Свободно
MTA (если мы находимся в MTA, так и будет; в противном случае COM создает его, который называется MTA хоста)
И то и другое
Какой бы ни была текущая квартира
нейтральный
Нейтральная квартира
Если вы, возможно, используете объекты MTA и сомневаетесь в том, что они "поточнобезопасны" (это обычно означает, что он будет использовать блокировку на уровне экземпляра при каждом вызове метода / свойства), то с этим вы ничего не поделаете. Например, у вас может быть несколько STA, обращающихся к одному и тому же объекту MTA одновременно.
Выполнение вызовов из STA не обязательно обеспечивает вам безопасность потока, если только вы не гарантируете, что нет других STA и никто больше не использует те же объекты.
"Гарантия" работает наоборот: все звонки, сделанные на STA, будут последовательными. Несмотря на это, повторные входящие вызовы разрешены, пока STA совершает междугородний вызов, так что это не является гарантией блокировки.
Сериализация вызовов действительно грубая, потому что она находится на уровне квартиры, поэтому все вызовы одной и той же STA, независимо от объекта, будут выполняться по одному за раз (но, возможно, один за другим с повторным входом).
РЕДАКТИРОВАТЬ: повторный вход вызова можно контролировать с помощью IMessageFilter.