Delen via


Single-Threaded Appartementen

Het gebruik van appartementen met één thread (het modelproces van het appartement) biedt een op berichten gebaseerd paradigma voor het verwerken van meerdere objecten die gelijktijdig worden uitgevoerd. Hiermee kunt u efficiëntere code schrijven door een thread toe te staan, terwijl er wordt gewacht tot een tijdrovende bewerking is voltooid, zodat een andere thread kan worden uitgevoerd.

Elke thread in een proces dat wordt geïnitialiseerd als een proces van een appartementsmodel en dat vensterberichten ophaalt en verzendt, is een single-threaded appartementsthread. Elke draad woont in een eigen appartement. Binnen een appartement kunnen interfaceaanwijzers worden doorgegeven zonder marshaling, en daarom communiceren alle objecten in één één threaded appartementsthread rechtstreeks.

Een logische groepering van gerelateerde objecten die allemaal op dezelfde thread worden uitgevoerd, en daarom synchrone uitvoering moet hebben, kan zich bevinden op dezelfde single-threaded appartementsthread. Een object van het appartementsmodel kan zich echter niet op meer dan één thread bevinden. Aanroepen naar objecten in andere threads moeten worden uitgevoerd binnen de context van de thread die eigenaar is, zodat gedistribueerde COM-threads automatisch worden ingeschakeld wanneer u een proxy aanroept.

De interprocessen en interthreadmodellen zijn vergelijkbaar. Wanneer het nodig is om een interfaceaanwijzer door te geven aan een object in een ander appartement (op een andere thread) binnen hetzelfde proces, gebruikt u hetzelfde marshaling-model dat objecten in verschillende processen gebruiken om aanwijzers over procesgrenzen te passeren. Door een aanwijzer te krijgen naar het standaard marshaling-object, kunt u marshal interface pointers over thread grenzen (tussen appartementen) op dezelfde manier doen als tussen processen. (Interfacepointers moeten marshaled worden wanneer ze tussen appartementen worden doorgegeven.)

Regels voor appartementen met één thread zijn eenvoudig, maar het is belangrijk om ze zorgvuldig te volgen:

  • Elk object mag slechts één draad (binnen een appartement met één thread) wonen.
  • Initialiseer de COM-bibliotheek voor elke thread.
  • Marshal wijst alle objecten aan wanneer ze tussen appartementen worden doorgegeven.
  • Elk appartement met één thread moet een berichtenlus hebben om oproepen van andere processen en appartementen binnen hetzelfde proces af te handelen. Appartementen met één thread zonder objecten (alleen client) hebben ook een berichtenlus nodig om de broadcastberichten te verzenden die door sommige toepassingen worden gebruikt.
  • DLL-objecten of in-process-objecten roepen de COM-initialisatiefuncties niet aan; In plaats daarvan registreren ze hun threadingmodel met het ThreadingModel benoemde waarde onder de InprocServer32 sleutel in het register. Appartementbewuste objecten moeten ook zorgvuldig DLL-toegangspunten schrijven. Er zijn speciale overwegingen die van toepassing zijn op threading in processervers. Zie In-Process serverthreadingproblemenvoor meer informatie.

Hoewel meerdere objecten op één thread kunnen leven, kan geen appartementsmodelobject op meer dan één thread leven.

Elke thread van een clientproces of out-of-process-server moet CoInitializeaanroepen of CoInitializeEx- aanroepen en COINIT_APARTMENTTHREADED opgeven voor de parameter dwCoInit. Het hoofd appartement is de thread die CoInitializeEx eerst aanroept. Zie In-Process Server Threading Issuesvoor meer informatie over in-process servers.

Alle aanroepen naar een object moeten worden gedaan op de draad (binnen het appartement). Het is verboden om een object rechtstreeks vanuit een andere thread aan te roepen; het gebruik van objecten op deze vrije thread-manier kan problemen veroorzaken voor toepassingen. De implicatie van deze regel is dat alle aanwijzers naar objecten moeten worden marshaled wanneer ze tussen appartementen worden doorgegeven. COM biedt de volgende twee functies voor dit doel:

Deze functies verpakken aanroepen naar CoMarshalInterface en CoUnmarshalInterface functies, waarvoor het gebruik van de MSHCTX_INPROC vlag is vereist.

Over het algemeen wordt de marshaling automatisch bereikt door COM. Wanneer u bijvoorbeeld een interfaceaanwijzer als een parameter doorgeeft in een methodeaanroep van een proxy naar een object in een ander appartement, of wanneer u CoCreateInstanceaanroept, wordt het marshaling automatisch uitgevoerd door COM. In sommige speciale gevallen, waarbij de schrijver van de toepassing interfacepointers doorgeeft tussen appartementen zonder gebruik te maken van de normale COM-mechanismen, moet de schrijver de marshaling handmatig afhandelen.

Als één appartement (Appartement 1) in een proces een interfaceaanwijzer heeft en een ander appartement (Appartement 2) het gebruik ervan vereist, moet Appartement 1 CoMarshalInterThreadInterfaceInStream aanroepen om de interface te marshalen. De stroom die door deze functie wordt gemaakt, is thread-safe en moet worden opgeslagen in een variabele die toegankelijk is voor Apartment 2. Appartement 2 moet deze stroom doorgeven aan CoGetInterfaceAndReleaseStream om de interface niet temarshaleren en krijgt een aanwijzer terug naar een proxy waarmee deze toegang heeft tot de interface. Het hoofd appartement moet actief blijven totdat de client alle COM-werkzaamheden heeft voltooid (omdat sommige in-process objecten in het hoofd appartement worden geladen, zoals beschreven in In-Process Server Threading Issues). Nadat één object op deze manier tussen threads is doorgegeven, is het heel eenvoudig om interfaceaanwijzers als parameters door te geven. Op die manier voert gedistribueerd COM de marshaling en thread-switch voor de toepassing uit.

Als u oproepen van andere processen en appartementen binnen hetzelfde proces wilt afhandelen, moet elk appartement met één thread een berichtenlus hebben. Dit betekent dat de werkfunctie van de thread een GetMessage-/DispatchMessage-lus moet hebben. Als andere synchronisatieprimitief worden gebruikt om te communiceren tussen threads, kan de functie MsgWaitForMultipleObjects worden gebruikt om zowel op berichten als op threadsynchronisatiegebeurtenissen te wachten. De documentatie voor deze functie bevat een voorbeeld van dit soort combinatielus.

COM maakt een verborgen venster met behulp van de Windows-klasse OleMainThreadWndClass in elk appartement met één thread. Er wordt een aanroep naar een object ontvangen als een vensterbericht naar dit verborgen venster. Wanneer het appartement van het object het bericht ophaalt en verzendt, ontvangt het verborgen venster het. De vensterprocedure roept vervolgens de bijbehorende interfacemethode van het object aan.

Wanneer meerdere clients een object aanroepen, worden de oproepen in de berichtenwachtrij geplaatst en ontvangt het object telkens wanneer het appartement berichten ophaalt en verzendt. Omdat de aanroepen worden gesynchroniseerd door COM en de aanroepen altijd worden geleverd door de thread die deel uitmaakt van het appartement van het object, hoeven de interface-implementaties van het object geen synchronisatie te bieden. Appartementen met één thread kunnen IMessageFilter implementeren om hen in staat te stellen oproepen te annuleren of vensterberichten te ontvangen wanneer dat nodig is.

Het object kan opnieuw worden ingevoerd als een van de interfacemethode-implementaties berichten ophaalt en verzendt of een ORPC-aanroep naar een andere thread doet, waardoor een andere aanroep naar het object wordt afgeleverd (door hetzelfde appartement). OLE voorkomt geen reentrancy op dezelfde thread, maar kan helpen bij het bieden van threadveiligheid. Dit is identiek aan de manier waarop een vensterprocedure opnieuw kan worden uitgevoerd als er berichten worden opgehaald en verzonden tijdens het verwerken van een bericht. Als u echter een niet-verwerkte single-threaded appartementsserver aanroept die een andere single-threaded appartementsserver aanroept, kan de eerste server opnieuw worden opgehaald.

toegang tot interfaces in verschillende appartementen

het threadingmodel kiezen

Multithreaded Apartments

In-Process problemen met serverthreading

processen, threads en appartementen

Single-Threaded en multithreaded Communication