Каковы ограничения потока STA по сравнению с потоками MTA? - PullRequest
17 голосов
/ 25 декабря 2010

Если мы создадим поток STA следующим образом: Thread.SetApartmentState(STA);, тогда он не сможет запустить код, помеченный атрибутом [MTAThread].

Мы видели [STAThread] в Windows и консольных приложениях, но я никогда не видел кода с атрибутом [MTAThread] и не знаю, какие библиотеки .NET используют этот атрибут.

Мой вопрос: каковы ограничения потока с состоянием квартиры, установленным на STA, по сравнению с потоками с состоянием квартиры MTA (естественные потоки .NET)?

Ответы [ 2 ]

18 голосов
/ 25 декабря 2010

тогда он не может запустить код, помеченный атрибутом [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 не поддерживает маршалинг. Единственный недостаток такого способа состоит в том, что каждый вызов будет маршалинг. Это медленно.

0 голосов
/ 25 декабря 2010

Я не думаю, что это имеет какое-то значение, если вы не используете COM.Если вы это сделаете, то в некоторых случаях COM-объекты могут быть доступны только из одного или другого типа потока.Если COM-объект работает в обеих квартирах, попробуйте выполнить тесты производительности.Или почитайте о СОМ квартирах на MSDN.Но я не думаю, что это имеет значение для производительности, это скорее выбор дизайна или что-то в этом роде.

...