Не могли бы вы объяснить STA и MTA?

391

Можете ли вы объяснить STA и MTA своими словами?

Кроме того, каковы жилые темы, и они относятся только к COM? Если так, то почему?

Джон
источник
1
Смотрите также: Понимание COM-квартир Часть 1 , Часть 2
17

Ответы:

361

Модель потоков COM называется моделью «квартиры», где контекст выполнения инициализированных объектов COM связан либо с одним потоком (однопотоковая квартира), либо со многими потоками (многопотоковая квартира). В этой модели объект COM, когда-то инициализированный в квартире, является частью этой квартиры на время ее выполнения.

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

Если COM-объект может обрабатывать свою собственную синхронизацию, тогда можно использовать модель MTA, где нескольким потокам разрешено взаимодействовать с объектом без маршализованных вызовов.

Джозеф Дейгл
источник
1
Рекомендуем прочитать более подробную информацию: ИНФОРМАЦИЯ: Описания и работа моделей потоков OLE .
сборник носов
208

Все зависит от того, как обрабатываются вызовы к объектам и насколько они нуждаются в защите. COM-объекты могут попросить среду выполнения защитить их от одновременного вызова несколькими потоками; те, которые не могут быть вызваны одновременно из разных потоков, поэтому они должны защищать свои собственные данные.

Кроме того, необходимо, чтобы среда выполнения не позволяла вызову COM-объекта блокировать пользовательский интерфейс, если вызов сделан из потока пользовательского интерфейса.

Квартира есть место для объектов , чтобы жить, и они содержат один или несколько потоков. Квартира определяет, что происходит, когда звонят. Вызовы к объектам в квартире будут приниматься и обрабатываться в любом потоке в этой квартире, за исключением того, что вызов потоком, уже находящимся в нужной квартире, обрабатывается сам по себе (т. Е. Прямой вызов объекта).

Нити могут быть либо в однопоточной квартире (в этом случае они являются единственной нитью в этой квартире), либо в многопоточной квартире. Они указывают, когда поток инициализирует COM для этого потока.

STA в первую очередь для совместимости с пользовательским интерфейсом, который привязан к определенному потоку. STA получает уведомления о вызовах для обработки, получая сообщение окна в скрытое окно; когда он делает исходящий вызов, он запускает модальный цикл сообщений, чтобы предотвратить обработку других оконных сообщений. Вы можете указать фильтр сообщений, который будет вызываться, чтобы ваше приложение могло отвечать на другие сообщения.

В отличие от этого все потоки MTA совместно используют один MTA для процесса. COM может запустить новый рабочий поток для обработки входящего вызова, если нет доступных потоков, вплоть до ограничения пула. Потоки исходящих звонков просто блокируются.

Для простоты мы рассмотрим только объекты, реализованные в DLL, которые объявляют в реестре о том, что они поддерживают, путем установки ThreadingModelзначения для ключа своего класса. Есть четыре варианта:

  • Основной поток ( ThreadingModelзначение отсутствует). Объект создается в главном потоке пользовательского интерфейса хоста, и все вызовы направляются в этот поток. Фабрика классов будет вызываться только в этом потоке.
  • Apartment, Это указывает на то, что класс может работать в любом потоке с однопоточным режимом. Если поток, который создает его, является потоком STA, объект будет выполняться в этом потоке, в противном случае он будет создан в основной STA - если основной STA не существует, для него будет создан поток STA. (Это означает, что потоки MTA, которые создают объекты Apartment, будут маршалировать все вызовы в другой поток.) ​​Фабрика классов может быть вызвана одновременно несколькими потоками STA, поэтому она должна защитить свои внутренние данные от этого.
  • Free, Это указывает на класс, предназначенный для запуска в MTA. Он всегда будет загружаться в MTA, даже если он создан потоком STA, что снова означает, что вызовы потока STA будут распределены. Это потому, что Freeобъект обычно пишется с ожиданием того, что он может заблокировать.
  • Both, Эти классы гибки и загружаются в любую квартиру, из которой они созданы. Однако они должны быть написаны так, чтобы соответствовать обоим наборам требований: они должны защищать свое внутреннее состояние от одновременных вызовов, если они загружены в MTA, но не должны блокироваться, если они загружены в STA.

Из .NET Framework, в основном, просто используйте [STAThread]любой поток, который создает пользовательский интерфейс. Рабочие потоки должны использовать MTA, если только они не собираются использовать ApartmentCOM-компоненты с метками, в этом случае используйте STA, чтобы избежать проблем с распределением ресурсов и масштабируемостью, если один и тот же компонент вызывается из нескольких потоков (поскольку каждому потоку придется ждать компонент по очереди). Все намного проще, если вы используете отдельный COM-объект для потока, независимо от того, находится ли компонент в STA или MTA.

Майк Диммик
источник
Мне нравится ваш последний вывод, но что касается того, что мне делать, если я хочу, чтобы в моем пользовательском интерфейсе был добавлен UserControl, единственное, что нужно сделать, это воспроизвести gif (как загрузчик) ... У меня проблемы с этим , gif не вращается, если они находятся в одном потоке ... и я не уверен, что MTA на UI - отличная идея, что бы вы сделали?
Йогурту
2
@Yogurtu: Почему вы вообще беспокоитесь о модели потоков COM? Решение STA / MTA имеет значение, только если вы используете COM-объекты в своем коде. Вы не можете использовать MTA для пользовательского интерфейса - внутренние компоненты .NET не предназначены для такого использования. Если ваша анимация останавливается, это потому, что вы перестали качать сообщения в своем потоке пользовательского интерфейса. Переместите длительные операции в BackgroundWorker или разбейте на маленькие шаги. Работа должна занять <16 мс, чтобы сохранить плавную 60 Гц анимацию!
Майк Диммик
В чем разница между «квартирой» и appdomain?
Puchacz
78

Я нахожу существующие объяснения слишком бессмысленными. Вот мое объяснение на простом английском:

STA: если поток создает COM-объект, для которого установлено значение STA (при вызове CoCreateXXX вы можете передать флаг, который устанавливает COM-объект в режим STA), то только этот поток может получить доступ к этому COM-объекту (это то, что означает STA - Single Threaded Apartment). ), другой поток, пытающийся вызвать методы этого COM-объекта, скрытно превращается в доставку сообщений потоку, который создает (владеет) COM-объект. Это очень похоже на тот факт, что только поток, создавший элемент управления пользовательского интерфейса, может получить к нему прямой доступ. И этот механизм предназначен для предотвращения сложных операций блокировки / разблокировки.

MTA: если поток создает COM-объект с установленным значением MTA, то почти каждый поток может напрямую вызывать методы для него.

Это в значительной степени суть этого. Хотя технически есть некоторые детали, которые я не упомянул, например, в параграфе «STA», потоком-создателем должен быть сам STA. Но это почти все, что вам нужно знать, чтобы понять STA / MTA / NA.

Weipeng L
источник
23

STA (Single Threaded Apartment) - это концепция, согласно которой только один поток будет взаимодействовать с вашим кодом одновременно. Звонки в вашу квартиру маршалируются через окна сообщений (используя невидимые) окна. Это позволяет звонкам ставиться в очередь и ждать завершения операций.

MTA (Multi-Threaded Apartment) - это место, где все потоки могут работать одновременно, и ответственность за безопасность потоков лежит на вас, как на разработчике.

Есть еще много информации о моделях многопоточности в COM, но если у вас возникли проблемы с пониманием того, что они из себя представляют, я бы сказал, что понимание того, что такое STA и как оно работает, было бы наилучшей отправной точкой, поскольку большинство объектов COM являются STA.

Потоки квартиры, если нить проживает в той же квартире, что и объект, который она использует, то это нить квартиры. Я думаю, что это всего лишь концепция COM, потому что это всего лишь способ говорить об объектах и ​​потоках, с которыми они взаимодействуют ...

Брайан Онейл
источник
19

Каждый EXE-файл, на котором размещены элементы управления COM или OLE, определяет состояние своей квартиры. Состояние квартиры по умолчанию STA (и для большинства программ должно быть STA).

STA - все элементы управления OLE по необходимости должны находиться в STA. STA означает, что вашим COM-объектом всегда нужно манипулировать в потоке пользовательского интерфейса и нельзя передавать в другие потоки (во многом как любой элемент пользовательского интерфейса в MFC). Тем не менее, ваша программа может иметь много потоков.

MTA - вы можете манипулировать объектом COM в любом потоке вашей программы.

Ник
источник
13
«STA означает, что вашим COM-объектом всегда нужно манипулировать в потоке пользовательского интерфейса». Я не думаю, что это совершенно верно ... он не обязательно должен быть в потоке «пользовательского интерфейса», только поток STA, имеющий накачка сообщений на него, потому что звонки синхронизируются с помощью сообщений. Поток пользовательского интерфейса обычно отвечает этим требованиям, но это не единственная возможность.
Брайан Онейл
12

Насколько я понимаю, «квартира» используется для защиты COM-объектов от многопоточности.

Если COM-объект не является потокобезопасным, он должен объявить его как STA-объект. Тогда только тот, кто его создает, может получить к нему доступ. Поток создания должен объявить себя как поток STA. Под капотом поток хранит информацию STA в своем TLS (Thread Local Storage). Мы называем это поведение тем, что поток входит в квартиру STA. Когда другие потоки хотят получить доступ к этому COM-объекту, он должен упорядочить доступ к потоку создания. По сути, поток создания использует механизм сообщений для обработки входящих вызовов.

Если COM-объект является потокобезопасным, он должен объявить его как MTA-объект. MTA-объект может быть доступен многопоточностью.

Кевин С.
источник
4

Код, который вызывает библиотеку COM-объектов (например, для чтения файлов проприетарных данных), может нормально работать в пользовательском интерфейсе, но таинственно зависать от службы. Причина в том, что в пользовательских интерфейсах .Net 2.0 предполагается STA (поточно-ориентированная), в то время как службы предполагают MTA ((до этого службы предполагали STA). Необходимость создания потока STA для каждого COM-вызова в службе может привести к значительным издержкам.

user2696845
источник