Udostępnij przez


Pomocnicy implementacji poza serwerem przetwarzania

Dostępne są cztery funkcje pomocnicze, które mogą być wywoływane przez serwery poza procesami, aby uprościć zadanie pisania kodu serwera. Klienci COM i serwery przetwarzania COM zwykle ich nie wywoływać. Te funkcje zostały zaprojektowane tak, aby zapobiegać warunkom wyścigu podczas aktywacji serwera, gdy serwery mają wiele mieszkań lub wielu obiektów klasy. Mogą być one jednak równie łatwe w przypadku serwerów obiektów jednowątkowych i jednoklasowych. Funkcje są następujące:

Aby prawidłowo zamknąć serwer COM, musi śledzić liczbę wystąpień obiektów, które zostały utworzone i ile razy jej IClassFactory::LockServer została wywołana. Tylko wtedy, gdy obie z tych liczb osiągną zero, może zostać zamknięty serwer. W przypadku pojedynczych wątkowych serwerów COM decyzja o zamknięciu została skoordynowana z przychodzącymi żądaniami aktywacji, które zostały serializowane przez kolejkę komunikatów. Serwer, po otrzymaniu wydania w ostatnim wystąpieniu obiektu i podjęciu decyzji o zamknięciu, odwoła obiekty klasy przed wysłaniem kolejnych żądań aktywacji. Jeśli żądanie aktywacji wystąpiło po tym punkcie, com rozpozna, że obiekty klasy zostały odwołane i zwróci błąd do Menedżera kontroli usług (SCM), co spowodowałoby uruchomienie nowego wystąpienia procesu serwera lokalnego.

Jednak na serwerze modelu apartamentów, w którym różne obiekty klasy są rejestrowane w różnych mieszkaniach, a we wszystkich serwerach bezwątkowy, decyzja o zamknięciu musi być skoordynowana z żądaniami aktywacji w wielu wątkach, aby jeden wątek serwera nie zdecydował się zamknąć, podczas gdy inny wątek serwera jest zajęty przekazywanie obiektów klasy lub wystąpień obiektów. Jednym z klasycznych, ale kłopotliwych metod rozwiązywania tego problemu jest posiadanie serwera, po odwołaniu obiektów klasy, ponowne sprawdzanie liczby wystąpień i pozostanie aktywne do momentu wydania wszystkich wystąpień.

Aby ułatwić pisarzom serwerów obsługę tych typów warunków wyścigu, COM udostępnia dwie funkcje zliczania odwołań:

Gdy globalna liczba odwołań dla procesu osiągnie zero, com automatycznie wywołuje CoSuspendClassObjects, co uniemożliwia nadejście nowych żądań aktywacji. Serwer może następnie wyrejestrować różne obiekty klasy z różnych wątków w wolnym czasie bez obaw, że może pojawić się inne żądanie aktywacji. Wszystkie nowe żądania aktywacji są w związku z tym obsługiwane przez narzędzie SCM uruchamiające nowe wystąpienie procesu serwera lokalnego.

Najprostszym sposobem używania tych funkcji przez aplikację serwera lokalnego jest wywołanie CoAddRefServerProcess w konstruktorze dla każdego obiektu wystąpienia i w każdym z jego IClassFactory::LockServer metod, gdy parametr fLock jest TRUE. Aplikacja serwera powinna również wywołać CoReleaseServerProcess w destruktorze każdego z jego obiektów wystąpienia i w każdym z jego IClassFactory::LockServer metod, gdy parametr fLock jest FALSE.

Na koniec aplikacja serwera powinna zwrócić uwagę na kod powrotny z CoReleaseServerProcess, a jeśli zwraca wartość 0, aplikacja serwera powinna zainicjować czyszczenie, które dla serwera z wieloma wątkami zwykle oznacza, że powinien zasygnalizować różne wątki, aby zakończyć pętle komunikatów i wywołać CoAddRefServerProcess i CoReleaseServerProcess. Jeśli są używane funkcje zarządzania okresem istnienia procesu serwera, muszą być używane zarówno w wystąpieniach obiektów, jak i metodę LockServer; w przeciwnym razie aplikacja serwera może zostać przedwcześnie zamknięta.

Gdy zostanie wykonane żądanieCoGetClassObject, com kontaktuje się z serwerem, marshaluje interfejs IClassFactory obiektu klasy, powraca do procesu klienta, co spowoduje usunięcie interfejsu IClassFactory i zwrócenie go do klienta. W tym momencie klienci zazwyczaj wywołuje LockServer z true, aby zapobiec zamykaniu procesu serwera. Istnieje jednak przedział czasu między czasem, kiedy obiekt klasy jest marshaled i kiedy klient wywołuje LockServer, w którym inny klient może nawiązać połączenie z tym samym serwerem, uzyskać wystąpienie i zwolnić to wystąpienie, powodując zamknięcie serwera i pozostawienie pierwszego klienta wysokiego i suchego z odłącz onym wskaźnikiem IClassFactory. Aby zapobiec temu stanowi wyścigu, com dodaje niejawne wywołanie do LockServer z TRUE do obiektu klasy, gdy uruchamia interfejs IClassFactory i niejawne wywołanie LockServer z FALSE, gdy klient zwalnia interfejs IClassFactory. W związku z tym nie jest konieczne zdalne LockServer wywołania z powrotem do serwera, a serwer proxy dla LockServer po prostu zwraca S_OK bez faktycznego komunikacji zdalnej wywołania.

Podczas inicjowania procesu serwera poza procesem przetwarzania występuje inny warunek wyścigu związany z aktywacją. Serwer COM rejestrujący wiele klas zwykle wywołuje CoRegisterClassObject z REGCLS_LOCAL_SERVER dla każdego obsługiwanego identyfikatora CLSID. Po wykonaniu tej czynności dla wszystkich klas serwer wprowadza pętlę komunikatów. W przypadku pojedynczego wątkowego serwera COM wszystkie żądania aktywacji są blokowane do momentu wprowadzenia pętli komunikatów przez serwer. Jednak w przypadku serwera modelu apartamentów, który rejestruje różne obiekty klasy w różnych mieszkaniach i dla wszystkich serwerów bezwątkowy, żądania aktywacji mogą zostać dostarczone wcześniej niż to. W przypadku serwerów modelu apartamentów żądania aktywacji mogą pojawić się zaraz po wprowadzeniu pętli komunikatów przez każdy wątek. W przypadku serwerów wolnych wątków żądanie aktywacji może zostać dostarczone zaraz po zarejestrowaniu obiektu pierwszej klasy. Ponieważ aktywacja może się zdarzyć na tym wczesnym etapie, możliwe jest również wystąpienie ostatecznego wydania (i w związku z tym spowodować, że serwer zacznie się zamykać), zanim pozostała część serwera miała szansę zakończyć inicjowanie.

Aby wyeliminować te warunki wyścigu i uprościć zadanie składnika zapisywania serwera, każdy serwer, który chce zarejestrować wiele obiektów klas w modelu COM, powinien wywołać CoRegisterClassObject z REGCLS_LOCAL_SERVER | REGCLS_SUSPENDED dla każdego identyfikatora CLSID obsługiwanego przez serwer. Po zarejestrowaniu wszystkich klas, a proces serwera jest gotowy do akceptowania przychodzących żądań aktywacji, serwer powinien wykonać jedno wywołanie CoResumeClassObjects. Ta funkcja informuje com o wszystkich zarejestrowanych klasach programu SCM i rozpoczyna zezwalanie na żądania aktywacji do procesu serwera. Korzystanie z tych funkcji zapewnia następujące korzyści:

  • Tylko jedno wywołanie jest wykonywane do SCM, niezależnie od liczby zarejestrowanych identyfikatorów CLSID, co zmniejsza całkowity czas rejestracji (a tym samym czas uruchamiania aplikacji serwera).
  • Jeśli serwer ma wiele mieszkań i różnych identyfikatorów CLSID są zarejestrowane w różnych mieszkaniach, lub jeśli serwer jest serwerem bez wątków serwera, żadne żądania aktywacji nie będą przychodzić do czasu wywołania serwera CoResumeClassObjects, dając serwerowi szansę zarejestrowania wszystkich jego identyfikatorów CLSID i uzyskania prawidłowej konfiguracji przed koniecznością obsługi żądań aktywacji i możliwego zamknięcia żądań.

obowiązki serwera COM