Czy możesz wyjaśnić STA i MTA?


Odpowiedzi:


361

Model wątków COM jest nazywany modelem „apartamentowym”, w którym kontekst wykonania zainicjowanych obiektów COM jest powiązany z jednym wątkiem (Apartament z jednym wątkiem) lub wieloma wątkami (Apartament z wieloma wątkami). W tym modelu obiekt COM, po zainicjowaniu w mieszkaniu, jest częścią tego mieszkania na czas jego działania.

Model STA jest używany dla obiektów COM, które nie są bezpieczne dla wątków. Oznacza to, że nie obsługują własnej synchronizacji. Typowym zastosowaniem tego jest komponent interfejsu użytkownika. Jeśli więc inny wątek musi wchodzić w interakcję z obiektem (na przykład naciśnięcie przycisku w formularzu), wiadomość jest przekazywana do wątku STA. Przykładem tego jest system pompowania wiadomości w systemie Windows.

Jeśli obiekt COM może obsłużyć własną synchronizację, wówczas można zastosować model MTA, w którym wiele wątków może wchodzić w interakcję z obiektem bez wywoływanych połączeń.


1
Dobra lektura dla dalszych szczegółów: INFO: Opisy i działanie modeli gwintowania OLE .
noseratio

208

Wszystko zależy od tego, jak obsługiwane są wywołania obiektów i ile potrzebują ochrony. Obiekty COM mogą prosić środowisko wykonawcze o ochronę przed wywołaniem przez wiele wątków jednocześnie; te, których nie można potencjalnie wywołać jednocześnie z różnych wątków, dlatego muszą chronić własne dane.

Ponadto środowisko wykonawcze musi również zapobiegać blokowaniu interfejsu użytkownika przez wywołanie obiektu COM, jeśli wywołanie jest wykonywane z wątku interfejsu użytkownika.

Mieszkanie jest miejscem dla obiektów do życia, a one zawierać jeden lub więcej wątków. Apartament określa, co się stanie, gdy zostaną wykonane połączenia. Połączenia z obiektami w mieszkaniu będą odbierane i przetwarzane na dowolnym wątku w tym mieszkaniu, z wyjątkiem tego, że wywołanie przez wątek już znajdujący się w odpowiednim mieszkaniu jest przetwarzane przez siebie (tj. Bezpośrednie wywołanie obiektu).

Wątki mogą znajdować się w mieszkaniu jednowątkowym (w takim przypadku są jedynym wątkiem w tym mieszkaniu) lub w mieszkaniu wielowątkowym. Określają one, kiedy wątek inicjuje COM dla tego wątku.

STA służy przede wszystkim do kompatybilności z interfejsem użytkownika, który jest powiązany z określonym wątkiem. Stacja STA odbiera powiadomienia o wywołaniach do przetworzenia, odbierając komunikat okna do ukrytego okna; kiedy wykonuje połączenie wychodzące, uruchamia modalną pętlę komunikatów, aby zapobiec przetwarzaniu innych komunikatów okna. Możesz określić filtr komunikatów, który ma być wywoływany, aby aplikacja mogła odpowiadać na inne wiadomości.

Natomiast wszystkie wątki MTA współużytkują jeden MTA dla tego procesu. COM może rozpocząć nowy wątek roboczy do obsługi połączenia przychodzącego, jeśli żadne wątki nie są dostępne, do limitu puli. Wątki wykonujące połączenia wychodzące po prostu blokują.

Dla uproszczenia weźmiemy pod uwagę tylko obiekty zaimplementowane w bibliotekach DLL, które reklamują w rejestrze, co obsługują, ustawiając ThreadingModelwartość klucza swojej klasy. Istnieją cztery opcje:

  • Główny wątek ( ThreadingModelwartość nie występuje). Obiekt jest tworzony w głównym wątku interfejsu użytkownika hosta, a wszystkie wywołania są kierowane do tego wątku. Fabryka klas będzie wywoływana tylko w tym wątku.
  • Apartment. Oznacza to, że klasa może działać na dowolnym wątku w trybie jednowątkowym. Jeśli tworzący go wątek jest wątkiem STA, obiekt będzie działał w tym wątku, w przeciwnym razie zostanie utworzony w głównej STA - jeśli nie istnieje główna STA, zostanie dla niej utworzony wątek STA. (Oznacza to, że wątki MTA, które tworzą obiekty Apartment, będą zbierać wszystkie wywołania innego wątku.) Fabrykę klas można wywoływać jednocześnie przez wiele wątków STA, więc musi chronić swoje dane wewnętrzne przed tym.
  • Free. Wskazuje to klasę zaprojektowaną do działania w MTA. Zawsze będzie ładował się do MTA, nawet jeśli zostanie utworzony przez wątek STA, co ponownie oznacza, że ​​wywołania wątku STA zostaną zestawione. Wynika to z faktu, że Freeobiekt jest zwykle zapisywany z oczekiwaniem, że może go zablokować.
  • Both. Klasy te są elastyczne i ładują się w dowolnym mieszkaniu, z którego zostały utworzone. Muszą być jednak napisane, aby pasowały do ​​obu zestawów wymagań: muszą chronić swój stan wewnętrzny przed równoczesnymi wywołaniami, na wypadek, gdyby zostały załadowane do MTA, ale nie mogą blokować, na wypadek, gdyby zostały załadowane do STA.

Z .NET Framework, po prostu użyj [STAThread]na dowolnym wątku, który tworzy interfejs użytkownika. ApartmentWątki robocze powinny używać MTA, chyba że zamierzają używać oznaczonych komponentów COM, w takim przypadku należy użyć STA, aby uniknąć problemów związanych z generowaniem i skalowaniem, jeśli ten sam komponent jest wywoływany z wielu wątków (ponieważ każdy wątek będzie musiał czekać na składnik z kolei). Wszystko jest o wiele łatwiejsze, jeśli używasz osobnego obiektu COM dla wątku, niezależnie od tego, czy składnik znajduje się w STA, czy MTA.


Podoba mi się twój ostatni wniosek, ale w związku z tym, co powinienem zrobić, jeśli chcę, aby mój interfejs użytkownika dodał UserControl, że jedyne, co robi, to odtworzyć gif (jak moduł ładujący) ... Mam z tym kłopoty , gif nie obraca się, jeśli są w tym samym wątku ... i nie jestem pewien, czy MTA w interfejsie użytkownika to świetny pomysł, co byś zrobił?
Yogurtu,

2
@Yogurtu: Dlaczego w ogóle martwisz się o model wątków COM? Decyzja STA / MTA jest istotna tylko wtedy, gdy używasz obiektów COM w kodzie. Nie można używać MTA do interfejsu użytkownika - wewnętrzne elementy .NET nie są przeznaczone do użycia w ten sposób. Jeśli animacja się zatrzyma, to dlatego, że przestałeś pompować wiadomości w wątku interfejsu użytkownika. Przenieś długotrwałe operacje do BackgroundWorker lub podziel na małe kroki. Praca musi zająć <16ms, aby utrzymać płynną animację 60 Hz!
Mike Dimmick

Jaka jest różnica między „mieszkaniem” a domeną?
Puchacz

78

Uważam, że istniejące wyjaśnienia są zbyt pochopne. Oto moje wyjaśnienie w prostym języku angielskim:

STA: Jeśli wątek tworzy obiekt COM, który jest ustawiony na STA (podczas wywoływania CoCreateXXX można przekazać flagę, która ustawia obiekt COM w tryb STA), tylko ten wątek może uzyskać dostęp do tego obiektu COM (to właśnie oznacza STA - Apartament z jednym wątkiem ), inny wątek próbujący wywołać metody dla tego obiektu COM jest pod maską cicho przekształcony w dostarczanie komunikatów do wątku, który tworzy (jest właścicielem) obiektu COM. Jest to bardzo podobne do faktu, że tylko wątek, który utworzył kontrolkę interfejsu użytkownika, może uzyskać do niego bezpośredni dostęp. Mechanizm ten ma na celu zapobieganie skomplikowanym operacjom blokowania / odblokowywania.

MTA: Jeśli wątek tworzy obiekt COM ustawiony na MTA, prawie każdy wątek może bezpośrednio wywoływać na nim metody.

To właściwie sedno tego. Chociaż technicznie są pewne szczegóły, o których nie wspomniałem, na przykład w akapicie „STA”, wątek twórcy musi być STA. Ale to prawie wszystko, co musisz wiedzieć, aby zrozumieć STA / MTA / NA.


23

STA (Single Threaded Apartment) to w zasadzie koncepcja, że ​​tylko jeden wątek będzie wchodził w interakcje z twoim kodem na raz. Połączenia z Twoim mieszkaniem są zestawiane za pomocą komunikatów systemu Windows (za pomocą niewidocznego) okna. Umożliwia to kolejkowanie połączeń i czekanie na zakończenie operacji.

MTA (Multi Threaded Apartment) to miejsce, w którym wiele wątków może działać w tym samym czasie, a na deweloperze spoczywa ciężar odpowiedzialności za bezpieczeństwo wątków.

Jest wiele więcej do nauczenia się o modelowaniu wątków w modelu COM, ale jeśli masz problemy ze zrozumieniem, czym one są, to powiedziałbym, że zrozumienie, czym jest STA i jak to działa, byłoby najlepszym miejscem początkowym, ponieważ większość obiektów COM to STA.

Wątki mieszkania, jeśli wątek mieszka w tym samym mieszkaniu co obiekt, którego używa, to jest to wątek mieszkania. Myślę, że to tylko koncepcja COM, ponieważ jest to tylko sposób mówienia o przedmiotach i wątkach, z którymi wchodzą w interakcje…


19

Każdy plik EXE, który obsługuje formanty COM lub OLE, określa stan apartamentu. Stan mieszkania to domyślnie STA (i dla większości programów powinna to być STA).

STA - Wszystkie kontrole OLE z konieczności muszą żyć w STA. STA oznacza, że ​​obiekt COM musi zawsze być modyfikowany w wątku interfejsu użytkownika i nie może być przekazywany do innych wątków (podobnie jak każdy element interfejsu użytkownika w MFC). Twój program może jednak mieć wiele wątków.

MTA - możesz manipulować obiektem COM w dowolnym wątku w swoim programie.


13
„STA oznacza, że ​​obiekt COM musi zawsze być modyfikowany w wątku interfejsu użytkownika”. Nie sądzę, że jest to dokładnie słuszne ... to nie musi być w wątku interfejsu użytkownika, tylko wątek STA, który ma pompa wiadomości na nim, ponieważ połączenia są zsynchronizowane za pomocą wiadomości. Wątek interfejsu użytkownika zwykle spełnia te wymagania, ale nie jest to jedyna możliwość.
Brian ONeil

12

W moim rozumieniu „Apartament” służy do ochrony obiektów COM przed problemami z wielowątkowością.

Jeśli obiekt COM nie jest bezpieczny dla wątków, powinien zadeklarować go jako obiekt STA. Wtedy tylko wątek, który go utworzy, będzie miał do niego dostęp. Wątek tworzenia powinien zadeklarować się jako wątek STA. Pod maską wątek przechowuje informacje STA w swoim TLS (Thread Local Storage). Takie zachowanie nazywamy tym, że nić wchodzi do mieszkania STA. Gdy inne wątki chcą uzyskać dostęp do tego obiektu COM, powinno ono zorganizować dostęp do wątku tworzenia. Zasadniczo wątek tworzenia używa mechanizmu komunikatów do przetwarzania wywołań przychodzących.

Jeśli obiekt COM jest bezpieczny dla wątków, powinien zadeklarować go jako obiekt MTA. Dostęp do obiektu MTA można uzyskać za pomocą wielu wątków.


4

Kod, który wywołuje biblioteki obiektów COM (na przykład w celu odczytu zastrzeżonych plików danych), może działać dobrze w interfejsie użytkownika, ale w tajemniczy sposób zawiesza się w usłudze. Powodem jest to, że od .Net 2.0 interfejsy użytkownika zakładają STA (bezpieczny dla wątków), podczas gdy usługi zakładają MTA ((wcześniej usługi zakładały STA). Konieczność utworzenia wątku STA dla każdego wywołania COM w usłudze może powodować znaczne obciążenie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.