Procesy, wątki i apartamenty

Proces to kolekcja przestrzeni pamięci wirtualnej, kodu, danych i zasobów systemowych. Wątek to kod, który jest wykonywany sekwencyjnie w obrębie procesu. Procesor wykonuje wątki, a nie procesy, więc każda aplikacja ma co najmniej jeden proces, a proces zawsze ma co najmniej jeden wątek wykonywania, znany jako wątek podstawowy. Proces może zawierać wiele wątków oprócz wątku podstawowego.

Procesy komunikują się ze sobą za pośrednictwem komunikatów przy użyciu technologii Remote Procedure Call (RPC) firmy Microsoft w celu przekazania informacji do siebie. Dla wywołującego nie ma różnicy między wywołaniem pochodzącym z procesu na zdalnej maszynie a wywołaniem pochodzącym z innego procesu na tej samej maszynie.

Gdy wątek rozpoczyna wykonywanie, wykonuje się dalej, dopóki nie zostanie zakończony lub nie zostanie przerwany przez wątek o wyższym priorytecie (na skutek działania użytkownika lub harmonogramu wątków jądra). Każdy wątek może uruchamiać oddzielne sekcje kodu lub wiele wątków może wykonywać tę samą sekcję kodu. Wątki wykonujące ten sam blok kodu zachowują oddzielne stosy. Każdy wątek w procesie udostępnia zmienne globalne i zasoby procesu.

Harmonogram wątków określa, kiedy i jak często należy wykonać wątek, zgodnie z kombinacją atrybutu klasy priorytetu procesu i priorytetu podstawowego wątku. Atrybut klasy priorytetu procesu można ustawić przez wywołanie funkcji SetPriorityClass i ustawić priorytet podstawowy wątku z wywołaniem polecenia SetThreadPriority.

Aplikacje wielowątkowe muszą unikać dwóch problemów związanych z wątkami: zakleszczeń i wyścigów. Impas występuje, gdy każdy wątek czeka na inne, aby coś zrobić. Mechanizm kontroli wywołań COM pomaga zapobiegać zakleszczeniom podczas wywołań między obiektami. Stan wyścigu występuje, gdy jeden wątek kończy działanie przed drugim, od którego zależy, co powoduje, że pierwszy używa niezainicjalizowanej wartości, ponieważ ten drugi nie dostarczył jeszcze prawidłowej wartości. COM dostarcza niektóre funkcje zaprojektowane specjalnie w celu uniknięcia warunków wyścigu na serwerach poza procesem. (Zobacz Narzędzia pomocnicze implementacji serwera poza procesem.)

Apartament i architektura wątkowa COM

Chociaż COM obsługuje model jednego wątku na proces, powszechny przed wprowadzeniem wielowątkowości, można pisać kod wykorzystujący wiele wątków, co pozwala tworzyć wydajniejsze aplikacje, ponieważ jeden wątek może być wykonywany, podczas gdy inny czeka na zakończenie czasochłonnej operacji.

Uwaga

Korzystanie z wielu wątków nie gwarantuje lepszej wydajności. W rzeczywistości, ponieważ faktoring wątków jest trudnym problemem, użycie wielu wątków często powoduje problemy z wydajnością. Kluczem jest użycie wielu wątków tylko wtedy, gdy masz bardzo pewność, co robisz.

 

Ogólnie rzecz biorąc, najprostszym sposobem wyświetlenia architektury wątkowania COM jest myślenie o wszystkich obiektach COM w procesie podzielonym na grupy o nazwie apartamenty. Obiekt COM mieszka w dokładnie jednym mieszkaniu, w sensie, że jego metody mogą być prawnie wywoływane tylko przez wątek, który należy do tego mieszkania. Każdy inny wątek, który chce wywołać obiekt, musi przejść przez serwer proxy.

Istnieją dwa rodzaje mieszkań: jednowątkowy apartament, a wielowątkowy apartament.

Ważna

Wybieranie modelu mieszkania (STA vs MTA):

Apartament CoInitializeEx flaga Użyj, gdy
STA (jednowątkowy) COINIT_APARTMENTTHREADED Twój wątek ma pętlę komunikatów (wątki interfejsu użytkownika) lub używasz obiektów COM, które wymagają mechanizmu obsługi komunikatów (kontrolki ActiveX, obiekty powłoki systemu, przeciąganie i upuszczanie).
MTA (wielowątkowy) COINIT_MULTITHREADED Wątek wykonuje pracę w tle bez pętli komunikatów, a używane obiekty COM są bezpieczne wątkowo lub zwinne.

Typowa pułapka zakleszczenia: Wątek STA musi przetwarzać komunikaty (za pomocą GetMessage/DispatchMessage lub rozwiązania równoważnego). Jeśli wątek STA blokuje element pierwotny synchronizacji (np. WaitForSingleObject) bez pompowania komunikatów, przychodzące wywołania COM do obiektów w tym mieszkaniu nigdy nie zostaną dostarczone — powodując zakleszczenia. Użyj CoWaitForMultipleHandles lub MsgWaitForMultipleObjects zamiast nieprzetworzonych oczekiwań na wątku STA.

  • Apartamenty jednowątkowe składają się dokładnie z jednego wątku, więc wszystkie obiekty COM znajdujące się w apartamencie jednowątkowym mogą odbierać wywołania metod wyłącznie od jedynego wątku należącego do tego apartamentu. Wszystkie wywołania metod obiektu COM w apartamencie jednowątkowym są synchronizowane z kolejką komunikatów systemu Windows dla wątku tego apartamentu jednowątkowego. Proces z pojedynczym wątkiem wykonywania jest po prostu specjalnym przypadkiem tego modelu.
  • Wielowątkowe apartamenty składają się z co najmniej jednego wątku, więc wszystkie obiekty COM, które mieszkają w wielowątkowym mieszkaniu, mogą odbierać wywołania metod bezpośrednio z dowolnego wątku należącego do wielowątkowego mieszkania. Wątki w wielowątkowym apartamencie korzystają z modelu o nazwie free-threading. Wywołania obiektów COM w wielowątkowym mieszkaniu są synchronizowane przez same obiekty.

Uwaga

Opis komunikacji między apartamentami jednowątkowymi i apartamentami wielowątkowymi w obrębie tego samego procesu można znaleźć w temacie Komunikacja między apartamentami jednowątkowymi i wielowątkowymi.

 

Proces może mieć zero lub więcej jednowątkowych apartamentów oraz zero lub jeden wielowątkowy apartament.

W procesie główny apartament jest inicjowany jako pierwszy. W jednym wątkowym procesie jest to jedyne mieszkanie. Parametry wywołania są przekazywane między apartamentami, a mechanizm COM obsługuje synchronizację za pomocą komunikatów. Jeśli określisz wiele wątków w procesie jako wielowątkowe, wszystkie te wątki będą znajdować się w jednym apartamencie, parametry będą przekazywane bezpośrednio do dowolnego wątku w tym apartamencie, a całą synchronizację musisz obsłużyć samodzielnie. W procesie z modelami free-threading i apartment threading wszystkie swobodne wątki znajdują się w jednym apartmentcie, a wszystkie pozostałe apartmenty są apartmentami jednowątkowymi. Proces działający z użyciem modelu COM jest zbiorem apartamentów, zawierającym co najwyżej jeden apartament wielowątkowy, ale dowolną liczbę apartamentów jednowątkowych.

Modele wątkowe w modelu COM zapewniają mechanizm dla klientów i serwerów korzystających z różnych architektur wątków do współpracy. Wywołania między obiektami z różnymi modelami wątków w różnych procesach są naturalnie obsługiwane. Z punktu widzenia obiektu wywołującego wszystkie wywołania obiektów poza procesem zachowują się identycznie, niezależnie od tego, jak wywoływany obiekt jest wątkowy. Podobnie, z perspektywy wywoływanego obiektu, wywołania przychodzące zachowują się identycznie, niezależnie od modelu wątkowego obiektu wywołującego.

Interakcja między klientem a obiektem działającym w innym procesie jest prosta, nawet jeśli korzystają z różnych modeli wątkowości, ponieważ klient i obiekt znajdują się w różnych procesach. COM, umieszczony między klientem a serwerem, może zapewnić kod umożliwiający współdziałanie modeli wątkowości, z wykorzystaniem standardowego marshallingu i RPC. Na przykład, jeśli obiekt jednowątkowy jest wywoływany jednocześnie przez wielu klientów wielowątkowych, wywołania zostaną zsynchronizowane przez COM poprzez umieszczenie odpowiednich komunikatów okiennych w kolejce komunikatów serwera. Mieszkanie obiektu będzie odbierać jedno wywołanie za każdym razem, gdy pobiera i wysyła komunikaty. Należy jednak zadbać o to, aby serwery przetwarzania działały prawidłowo ze swoimi klientami. (Zobacz In-Process Server Threading Issues.)

Najważniejszą kwestią w programowaniu w modelu wielowątkowym jest zapewnienie, aby kod był bezpieczny wątkowo, tak aby komunikaty przeznaczone dla określonego wątku trafiały wyłącznie do tego wątku, a dostęp do wątków był odpowiednio chroniony.

Aby uzyskać więcej informacji, zobacz następujące tematy: