STAThread и многопоточность

Из статьи MSDN о STAThread:

Указывает, что модель потока COM для приложения является однопоточным (STA).

(Для справки, это вся статья.)

Однопоточная квартира... Хорошо, это прошло через мою голову. Кроме того, я где-то читал, что, если ваше приложение не использует COM-взаимодействие, этот атрибут фактически ничего не делает. Так что именно он делает, и как это влияет на многопоточные приложения? Должны многопоточные приложения (которые включают в себя что-нибудь от любого, кто использует Timerдля асинхронных вызовов методов, а не только для потоковых пулов и т. п.) использовать MTAThread, даже если это "просто для безопасности"? Что на самом деле делают STAThread и MTAThread?

3 ответа

Решение

Резьба в квартире - это концепция COM; если вы не используете COM, и ни один из API-интерфейсов, которые вы называете, не использует COM "под прикрытием", вам не нужно беспокоиться о квартирах.

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

Что это делает это гарантирует, что CoInitialize вызывается с указанием COINIT_APARTMENTTHREADED в качестве параметра. Если вы не используете какие-либо компоненты COM или элементы управления ActiveX, это никак не повлияет на вас. Если вы это сделаете, то это очень важно.

Управляющие элементы, являющиеся многопоточными, фактически являются однопоточными, вызовы к ним могут обрабатываться только в той квартире, в которой они были созданы.

Еще немного подробностей из MSDN:

Объекты, созданные в однопотоковой квартире (STA), получают вызовы методов только из потока своей квартиры, поэтому вызовы сериализуются и поступают только к границам очереди сообщений (когда вызывается функция Win32 PeekMessage или SendMessage).

Объекты, созданные в потоке COM в многопоточной квартире (MTA), должны иметь возможность получать вызовы методов из других потоков в любое время. Обычно вы реализуете некоторую форму управления параллелизмом в коде многопоточного объекта, используя примитивы синхронизации Win32, такие как критические секции, семафоры или мьютексы, чтобы помочь защитить данные объекта.

Когда объект, настроенный для работы в нейтральной многопоточной квартире (NTA), вызывается потоком, который находится либо в STA, либо в MTA, этот поток переходит к NTA. Если этот поток впоследствии вызывает CoInitializeEx, вызов завершается неудачно и возвращает RPC_E_CHANGED_MODE.

STAThread пишется перед основной функцией проекта C# GUI. Это ничего не делает, но позволяет программе создать единый поток.

Другие вопросы по тегам