Можете ли вы объяснить STA и MTA своими словами?
Кроме того, что такое потоки квартир и они относятся только к COM? Если да, то почему?
Можете ли вы объяснить STA и MTA своими словами?
Кроме того, что такое потоки квартир и они относятся только к COM? Если да, то почему?
Модель потоковой передачи COM называется моделью "квартиры", где контекст выполнения инициализированных COM-объектов связан либо с одним потоком (одноволоконная квартира), либо с несколькими потоками (многопотоковая квартира). В этой модели COM-объект, однажды инициализированный в квартире, является частью этой квартиры на время ее выполнения.
Модель STA используется для объектов COM, которые не являются потокобезопасными. Это означает, что они не выполняют свою собственную синхронизацию. Общим использованием этого является компонент пользовательского интерфейса. Поэтому, если другой поток должен взаимодействовать с объектом (например, нажимать кнопку в форме), тогда сообщение сортируется по потоку STA. Примером этого является система обработки сообщений в окнах.
Если COM-объект может обрабатывать свою собственную синхронизацию, тогда модель MTA может использоваться, когда нескольким потокам разрешено взаимодействовать с объектом без упорядоченных вызовов.
Все зависит от того, как обрабатываются обращения к объектам, и насколько нужна защита. COM-объекты могут запрашивать среду выполнения, чтобы защитить их от одновременного вызова несколькими потоками; те, которые не могут быть вызваны одновременно из разных потоков, поэтому они должны защищать свои собственные данные.
Кроме того, для среды выполнения также необходимо, чтобы вызов COM-объекта блокировал пользовательский интерфейс, если вызов выполняется из потока пользовательского интерфейса.
Квартира - это место для жизни объектов, и они содержат один или несколько потоков. В квартире определяется, что происходит, когда звонки производятся. Звонки на объекты в квартире будут приниматься и обрабатываться в любом потоке в этой квартире, за исключением того, что вызов по потоку уже в правой квартире обрабатывается сам по себе (то есть прямой вызов объекта).
Нитки могут быть либо в однопоточной квартире (в этом случае они являются единственной нитью в этой квартире), либо в многопоточной квартире. Они указывают, когда поток инициализирует COM для этого потока.
STA в первую очередь совместима с пользовательским интерфейсом, привязанным к определенному потоку. STA получает уведомления о вызовах для обработки, получая оконное сообщение в скрытое окно; когда он выполняет исходящий вызов, он запускает модальный цикл сообщений, чтобы предотвратить обработку других оконных сообщений. Вы можете указать фильтр сообщений для вызова, чтобы ваше приложение могло отвечать на другие сообщения.
В отличие от всех потоков MTA используется один MTA для процесса. COM может запустить новый рабочий поток для обработки входящего вызова, если потоки не доступны, вплоть до предела пула. Потоки, исходящие исходящие вызовы, просто блокируются.
Для простоты мы рассмотрим только объекты, реализованные в DLL, которые рекламируют в реестре то, что они поддерживают, установив значение ThreadingModel
для своего ключа класса. Существует четыре варианта:
ThreadingModel
значение отсутствует). Объект создается в главном потоке пользовательского интерфейса хоста, и все вызовы сопоставляются с этим потоком. Класс factory будет вызываться только в этом потоке.Apartment
. Это означает, что класс может работать в потоке с одним потоком. Если поток, который его создает, является потоком STA, объект будет работать в этом потоке, иначе он будет создан в главной STA - если не существует основной STA, для него будет создан поток STA. (Это означает, что потоки MTA, которые создают объекты квартиры, будут сортировать все вызовы в другом потоке.) Класс factory может вызываться одновременно несколькими потоками STA, поэтому он должен защищать свои внутренние данные от этого.Free
. Это указывает класс, предназначенный для запуска в MTA. Он всегда будет загружаться в MTA, даже если он создается потоком STA, что снова означает, что вызовы потоков STA будут распределены. Это связано с тем, что объект Free
обычно записывается с ожиданием его блокировки.Both
. Эти классы гибки и загружаются в любую квартиру, из которой они созданы. Они должны быть написаны с учетом обоих наборов требований: они должны защищать свое внутреннее состояние от одновременных вызовов, если они загружены в MTA, но не должны блокироваться, если они загружены в STA.Из .NET Framework просто используйте [STAThread]
для любого потока, создающего интерфейс. Рабочие потоки должны использовать MTA, если только они не будут использовать Apartment
-маркированные COM-компоненты, и в этом случае используйте STA, чтобы избежать сбоев в работе и проблем с масштабируемостью, если один и тот же компонент вызывается из нескольких потоков (поскольку каждый поток будет иметь дождаться компонента в свою очередь). Это намного проще, если вы используете отдельный COM-объект для каждого потока, независимо от того, находится ли компонент в STA или MTA.
Я нахожу, что существующие объяснения тоже слишком жаль. Здесь мое объяснение на простом английском языке:
STA: Если поток создает COM-объект, который установлен в STA (при вызове CoCreateXXX вы можете передать флаг, который устанавливает COM-объект в режим STA), тогда только этот поток может получить доступ к этому COM-объекту (что означает, что STA означает однопоточную квартиру) другой поток, пытающийся вызвать методы на этом объекте COM, находится под капотом, который молча превращается в доставку сообщений в поток, который создает (владеет) COM-объект. Это очень похоже на то, что только поток, создавший элемент управления пользовательского интерфейса, может получить к нему доступ напрямую. И этот механизм предназначен для предотвращения сложных операций блокировки/разблокировки.
MTA: Если поток создает COM-объект, который установлен в MTA, то почти каждый поток может напрямую вызывать методы на нем.
Это в значительной степени суть этого. Хотя технически есть некоторые подробности, которые я не упоминал, например, в параграфе "STA", поток создателя сам должен быть STA. Но это почти все, что вам нужно знать, чтобы понять STA/MTA/NA.
Каждый EXE, который содержит элементы управления COM или OLE, определяет это состояние квартиры. Состояние квартиры по умолчанию STA (и для большинства программ должно быть STA).
STA. Все элементы OLE по необходимости должны жить в STA. STA означает, что ваш COM-объект должен всегда управляться потоком пользовательского интерфейса и не может быть передан другим потокам (как и любой элемент пользовательского интерфейса в MFC). Однако ваша программа все еще может иметь много потоков.
MTA. Вы можете манипулировать COM-объектом в любом потоке вашей программы.
STA (Single Threaded Apartment) - это в основном концепция, что только один поток будет взаимодействовать с вашим кодом за раз. Звонки в вашу квартиру сортируются через окна сообщений (используя невидимое) окно. Это позволяет звонить в очередь и ждать завершения операций.
MTA (Multi Threaded Apartment) - это то, где многие потоки могут работать одновременно, а бремя на вас, как разработчика, для защиты потоков.
Намного больше узнать о потоковых моделях в COM, но если у вас возникнут проблемы с пониманием того, что они есть, я бы сказал, что понимание того, что такое STA и как это работает, было бы лучшим стартовым местом, потому что большинство COM-объектов являются STA.
Квартира Threads, если нить живет в той же квартире, что и объект, который она использует, то это нить квартиры. Я думаю, что это только концепция COM, потому что это всего лишь способ говорить об объектах и потоках, с которыми они взаимодействуют...
Как я понимаю, "Квартира" используется для защиты объектов COM от многопоточных проблем.
Если COM-объект не является потокобезопасным, он должен объявлять его как объект STA. Тогда только поток, который его создает, может получить к нему доступ. Нить создания должна объявлять себя как поток STA. Под капотом поток хранит информацию STA в своем TLS (локальное хранилище потоков). Мы называем это поведение тем, что поток входит в квартиру STA. Когда другие потоки хотят получить доступ к этому COM-объекту, он должен маршировать доступ к потоку создания. В принципе, поток создания использует механизм сообщений для обработки входящих вызовов.
Если COM-объект является потокобезопасным, он должен объявить его как объект MTA. К объекту MTA можно обращаться по нескольким потокам.
Код, который вызывает DLL-объекты COM-объекта (например, для чтения проприетарных файлов данных), может работать нормально в пользовательском интерфейсе, но таинственно таинственно из сервиса. Причина в том, что с .Net 2.0 пользовательские интерфейсы предполагают STA (потокобезопасность), в то время как сервисы предполагают MTA ((до этого, сервисы предполагались STA). Необходимость создания потока STA для каждого COM-вызова в сервисе может добавить значительные накладные расходы.