тогда он не может запустить код, помеченный атрибутом [MTAThread].
Это не так, как это работает. Тип квартиры - это свойство потока, а не метода. Вы видите атрибут [STAThread], применяемый только к методу Main () программы .NET. Он определяет тип квартиры самого первого потока, созданного для запуска программы. Необходимо, потому что вы не можете вызывать SetApartmentState () после запуска потока. Кроме того, атрибут не имеет значения, поток остается в STA в течение всего срока его службы. Вы никогда не увидите [MTAThread], потому что это по умолчанию.
Поток, который является STA, имеет некоторые ограничения. Он никогда не может блокировать, потому что это блокирует и часто блокирует любой код, который пытается вызвать метод COM-объекта с многопоточной квартирой. И он должен прокачать цикл сообщений, чтобы COM мог маршалировать вызов метода из другого потока. Вызовы методов Marshaled могут быть выполнены только в том случае, если поток находится в режиме ожидания и не занят выполнением какого-либо кода. Цикл сообщений обеспечивает состояние «не занят».
Есть также требования к компоненту COM. Он должен поддерживать маршалинг, либо ограничив себя подмножеством типов, поддерживаемых Automation, чтобы можно было использовать стандартный маршаллер. Или предоставив пару прокси / заглушки для пользовательского маршалинга. Раздел реестра HKCR\Interface\{iid}\ProxyStubClsid32
определяет порядок выполнения маршалинга.
Явно поддерживается совместное использование многопоточного объекта между STA и MTA-потоком. Поток STA должен его создать, любые вызовы в потоке MTA (или других потоках STA) маршалируются. Это гарантирует, что компонент только когда-либо видит вызовы, сделанные в одном потоке, что обеспечивает безопасность потока. Никакой дополнительной блокировки не требуется.
И последнее, но не менее важное: если вы создаете многопоточный COM-объект в потоке MTA, то COM автоматически создаст STA-поток, чтобы обеспечить его безопасность. Единственный режим отказа для этого - когда компонент COM не поддерживает маршалинг. Единственный недостаток такого способа состоит в том, что каждый вызов будет маршалинг. Это медленно.