STAThread та багатопоточна


102

З статті MSDN про STAThread:

Вказує, що модель різьблення COM для програми - це однопоточна квартира (STA).

(Для довідки, це вся стаття .)

Квартира з однією різьбою ... Добре, що мені перейшло через голову. Крім того, я десь читав, що якщо ваша програма не використовує інтероп COM, цей атрибут насправді нічого не робить. Отже, що саме це робить, і як це впливає на багатопотокові програми? Чи повинні багатопотокові програми (що включає в себе що-небудь від тих, хто використовує Timers для асинхронних викликів методів, а не лише потокові пули тощо), використовуючи MTAThread, навіть якщо це "просто для безпеки"? Що насправді робить STAThread та MTAThread?

Відповіді:


60

Нарізка квартир - це концепція COM; якщо ви не використовуєте COM, і жоден з API, який ви називаєте, не використовує COM "під кришками", то вам не потрібно турбуватися про квартири.

Якщо вам потрібно знати про квартири, то деталі можуть стати трохи складнішими ; ймовірно, спрощена версія полягає в тому, що об'єкти COM, позначені як STA, повинні бути запущені на STAThread, а COM-об’єкти, позначені MTA, повинні бути запущені на потоці MTA. Використовуючи ці правила, COM може оптимізувати дзвінки між цими різними об'єктами, уникаючи маршалінгу там, де це не потрібно.


7
Це надто спрощено. Багатопотокові об'єкти можуть працювати в будь-якій нитці. Квартира з різьбленням об'єкти можуть працювати тільки в квартирі вони були створені.
1800 ІНФОРМАЦІЮ

28
Виклик від об'єкта STA на потоці STA, до об'єкта MTA, перейде до потоку MTA (якщо об'єкт MTA не реалізує маршалер вільних потоків). Як я вже сказав, деталі можуть ускладнитися. (Я працював над командою COM протягом багатьох років, усміхнувшись )
Брюс

9
Іноді вам потрібно знати про це, навіть якщо ви безпосередньо не використовуєте COM. Нитка повинна використовувати модель однониткової квартири, якщо вона відображає графічні вікна. Ось чому [STAThread] завжди відображається над основним методом у програмі Windows form.
Джастін Етьє

6
Не вдалося щось подібне до діалогу «Шрифт або Файл» використовувати COM, не знаючи? Я б припустив, що вони роблять всередині, чи не означає це, що майже будь-яка програма Windows Forms потребує встановлення STAThread? Пробачте моє припущення, що я насправді не займався програмуванням COM.
Бретт Райан

4
Більш докладну відповідь для тих, хто зацікавлений: stackoverflow.com/questions/4154429/apartmentstate-for-dummies
jgauffin

3

Що це робить, це забезпечує, CoInitializeназивається вказівкою параметра COINIT_APARTMENTTHREADED як параметра. Якщо ви не використовуєте жодних компонентів COM або елементів керування ActiveX, це взагалі не вплине на вас. Якщо ви це зробите, то це наче важливо.

Елементи управління, які є потоковими в квартирі, є одномоментними, дзвінки, зроблені на них, можуть оброблятися лише в квартирі, в якій вони були створені.

Ще кілька деталей з MSDN:

Об'єкти, створені в однопотоковій квартирі (STA), отримують виклики методу лише з потоку їх квартири, тому виклики серіалізуються та надходять лише на межі черги повідомлень (коли викликається функція Pe32Message або SendMessage Win32).

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

Коли об'єкт, який налаштований для запуску в квартирі з нейтральною ниткою (NTA), викликається потоком, який знаходиться або в STA, або в MTA, цей потік передається в NTA. Якщо цей потік згодом викликає CoInitializeEx, виклик закінчується і повертає RPC_E_CHANGED_MODE.


Стаття MSDN корисна з точки зору COM, але чи можете ви сказати мені, коли .NET дзвонить CoInitialize()у відповідь на STAThreadатрибут / ApartmentState? Примітка: Стаття про MSDN знаходиться тут: функція CoInitializeEx .
jrh

Чи використовує нитку-> SetApartmentCoInitialize() внутрішньо? Я простежив атрибут STAThread аж донизу, але слід холодно (я не можу знайти джерело Thread::SetApartment). Чи кудись задокументований клас "Thread" від thread.h (COM thread.h)? Це MFC, ATL чи щось інше?
jrh

@jrh Я не знаю більше деталей, ніж це шкода
1800 ІНФОРМАЦІЯ

-15

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.