Präsentation herunterladen
1
COM & Threading „The Basics“
Frank Lange Michael Willers Microsoft GmbH
2
Agenda Warum COM-Threading? Wie funktioniert’s?
Wo gibt’s weitere Info’s?
3
Warum COM-Threading? Ein einfaches Beispiel
Zwei Threads innerhalb eines Prozesses erzeugen das gleiche COM-Object. Ist der COM-Server eine DLL (in-proc) dann greifen die Methoden beider Objektinstanzen auf die gleichen globalen Daten zu. Sofern der Zugriff nicht threadsafe ist “krachts”, wenn beide Threads auf die globalen Daten zugreifen. Object (Instanz 1) Thread 1 Globale Daten Object (Instanz 2) Thread 2
4
Warum COM-Threading? Was bedeutet Threading Model?!
5
Warum COM-Threading? “Brauchen“ Sie performante Objekte?
Im “Multithread-Betrieb” können in “bestimmten” Situationen keine direkten Methodenaufrufe erfolgen. In diesen Situationen ist Marshalling notwendig; Aufrufe werden langsamer! Wann ist das Marshalling notwendig?
6
Wie funktioniert‘s? Allgemeines, I
Standardmäßig “schützt” COM die Objekte vor dem Zugriff konkurrierender Threads (SingleThreading). Zugriffe werden synchronisiert (Standard!) Client braucht nicht darauf zu achten, ob das Objekt threadsafe ist Bei “echtem” Multithreading muß der Entwickler dafür sorgen, daß die Objekte threadsafe sind !!! Threading wird mit Apartments realisiert.
7
Wie funktioniert‘s? Was bedeutet Apartment?
Ein Apartment ist eine Gruppe von Objekten innerhalb eines Prozesses. Apartments werden benutzt, um eine Zuordnung zwischen Threads und Objekten herzustellen. Ein Prozeß kann ein oder mehrere Apartments beinhalten.
8
Wie funktioniert‘s? Beispiele für Apartments
Apartment A Apartment B Apartment C Prozess X Prozess Y
9
Wie funktioniert‘s? Was bedeutet Apartment?
Single-threaded apartments (STAs) pro Apartment nur ein einziger Thread beliebig viele STAs pro Prozess Der innerhalb eines Prozesses zuerst erzeugte STA heißt main STA Multithreaded apartments (MTAs) beliebig viele Threads pro MTA ein Prozess kann nur genau ein MTA beinhalten
10
Wie funktioniert‘s? Allgemeines, II
Jeder Thread, der mit COM-Objekten arbeitet, muß vorher CoInitialize oder CoInitializeEx aufrufen. Mit diesem Aufruf “betritt” der Thread ein Apartment Jedes Objekt befindet sich in einem Apartment Objekte in unterschiedlichen Apartments können nicht “direkt” aufgerufen werden. In diesem Fall ist Marshalling notwendig! gilt auch innerhalb eines Prozesses!
11
Wie funktioniert‘s? Objekte, Threads und Apartments
main STA Thread 1 Marshalling STA Thread 2 Prozess Marshalling MTA Thread 3 Thread 4
12
Wie funktioniert‘s? Aufrufe in andere Apartments
“Ziel-Apartment” ist ein STA… Aufrufe werden an den “one and only” Thread des STA weitergeleitet und nacheinander abgearbeitet (serially) Aufruf wird mit einer Nachricht realisiert, die an ein von COM erzeugtes “hidden window” gesendet wird (message queuing!) “Ziel-Apartment” ist ein MTA… Aufrufe geschehen quasi “gleichzeitig” (concurrency) via (L)RPC
13
Wie funktioniert‘s? Zuordnung: Threads und Apartments
Der 2. Parameter von CoInitializeEx (COINIT-Wert) legt fest, in welchem Apartment-Typ der Thread “läuft”. COINIT_APARTMENTTHREADED “setzt” den Thread in ein STA COINIT_MULTITHREADED “setzt” den Thread in ein MTA CoInitialize = CoInitializeEx (…, COINIT_APARTMENTTHREADED )
14
Wie funktioniert‘s? Zuordnung: Objekte und Apartments, I
Out-of-proc (EXE) Der Server, in dem sich das Objekt befindet, bestimmt den Apartmenttyp! Die main-Funktion des Servers ruft CoInitialize bzw. CoInitializeEx auf. Reminder: Jeder Thread, der mit COM-Objekten arbeitet, muß diese Funktion aufrufen D.h.: Der Apartmenttyp wird für alle Objekte des Servers festgelegt! ACHTUNG: Wenn der Apartmenttyp MTA ist, müssen alle Objekte des Servers threadsafe sein!
15
Wie funktioniert‘s? Zuordnung: Objekte und Apartments, II
In-proc (DLL) Das Threading Model des Objekts bestimmt den Apartmenttyp! Das Threading Model ist in der Registry gespeichert. D.h.: Der Apartmenttyp wird für jedes Objekt einzeln festgelegt!
16
Wie funktioniert‘s? Threading Model in der Registry
HKEY_CLASSES_ROOT CLSID {…} “My Component” InprocServer32 “C:\Servers\MyComp.dll” “ThreadingModel” “Apartment” An dieser Stelle ist das Threading Model eingetragen!
17
Wie funktioniert‘s? Welche Threading Model‘s gibt es?, I
No ThreadingModel value (=Single) Alle Objekte “laufen” im main STA eines Prozesses
18
Wie funktioniert‘s? Welche Threading Model‘s gibt es?, II
ThreadingModel=Apartment Objekte können in jedem STA eines Prozesses “laufen” ThreadingModel=Free Objekte “laufen” grundsätzlich nur im “one and only” MTA eines Prozesses ThreadingModel=Both Objekte können sowohl in einem STA als auch im MTA eines Prozesses “laufen”
19
Wie funktioniert‘s? No Threading Model (=Single)
COM “nimmt” an, daß Objekte nicht threadsafe sind. COM “beschränkt” alle Objekt-Instanzen auf das main STA. Aufrufe von ausserhalb werden synchronisiert und erfolgen indirekt (marshalling) Da alle Instanzen im gleichen Thread laufen kann immer nur eine einzige Instanz “Code ausführen”. Voila! Thread safety!
20
Wie funktioniert‘s? No Threading Model (=Single)
Methodenaufrufe werden synchronisiert, da ALLE Objekt-Instanzen im gleichen Thread „laufen”. Somit sind gleichzeitige Zugriffe auf globale Daten nicht möglich. main STA Thread 1 Instanz 1 Instanz 2 Marshalling Alle anderen Apartments Thread 2 Proxy (gilt für Zugriffe „innerhalb“ von Methoden)
21
Wie funktioniert‘s? Threading Model=Apartment
COM “nimmt” an, daß Objekte “halbwegs” threadsafe sind und “setzt” Objekt in ein STA. COM synchronisiert Methodenaufrufe innerhalb einzelner Objektinstanzen. Somit sind auch Member einer Instanz geschützt. Methodenaufrufe unterschiedlicher Instanzen können gleichzeitig erfolgen. Wird innerhalb dieser Methoden auf globale Daten zugegriffen, muß dieser Zugriff threadsafe sein. Jeder Thread, der in einem STA “läuft” kann dort Objekte erstellen. Zugriffe auf diese Objekte können aus MTA’s nur indirekt erfolgen (Marshalling).
22
Wie funktioniert‘s? Threading Model=Apartment
main STA Thread 1 Instanz 1 Global Daten STA Thread 2 Instanz 2 Globale Daten werden nicht vor “überlappenden” Lese- und Schreibzugriffen verschiedener Instanzen geschützt und müssen synchronisiert werden.
23
Wie funktioniert‘s? Threading Model=Free
COM “nimmt” an, das Objekte threadsafe sind. D.h.: “Concurrent calls” sind OK. COM braucht Methodenaufrufe nicht zu synchronisieren COM “setzt” Objekte in den MTA und alle dortigen Threads können direkt, d.h. ohne Marshalling, auf die Objekte zugreifen. Threads, die in STAs “laufen” können auf die Objekte im MTA nur indirekt zugreifen (Marshalling!).
24
Wie funktioniert‘s? Threading Model=Both
COM “nimmt” an, das Objekte grundsätzlich threadsafe sind. Ein Objekt kann in einem STA oder dem MTA angelegt werden. Dadurch ist sichergestellt, daß das Objekt stets im Apartment des Client-Threads angelegt wird. Es ist egal, ob der Client ein STA-Thread oder ein MTA-Thread ist Der Thread, der das Objekt angelegt hat, kann stets direkt auf das Objekt zugreifen
25
Wie funktioniert‘s? Wann erfolgt Marshalling?
Alle weiteren Threads, die CoInitializeEx (COINIT_APARTMENTTHREADED) aufrufen Allererster Thread, der CoInitializeEx (COINIT_APARTMENTTHREADED) aufruft Alle Threads, die CoInitializeEx COINIT_MULTITHREADED) aufrufen ThreadingModel MTA Thread STA Thread Main STA Thread “Both” Direkt Direkt Direkt “Apartment” Proxy Direkt Direkt Kein Eintrag (none) Proxy Proxy Direkt “Free” Direkt Proxy Proxy
26
Wie funktioniert‘s? Was muss implementiert werden?
Threading Model Aktion None (Single) nichts Apartment Synchronisation für Methodenzugriffe auf globale Daten Free Synchronisation für Methodenzugriffe auf globale Daten und Instanzdaten (Member) Both Synchronisation für Methodenzugriffe auf globale Daten und Instanzdaten (Member)
27
Wie funktioniert‘s? Warum „Free“ und „Both“
Es gibt Objekte, die selbst Worker-Threads erzeugen: Diese Threads sollen vorhandene Schnittstellenzeiger benutzen. Wenn man diese Objekte als "Both" deklariert und in einem STA erzeugt, müssen die Worker-Threads in anderen Apartments erzeugt werden. Schnittstellenzeiger werden also„gemarshalled“. Dies kann bei häufigen Aufrufen erhebliche Performanceverluste verursachen. Für diese Fälle kann man mit „Free" die Erzeugung im MTA erzwingen. Die Worker-Threads und das Objekt befinden sich dann im selben Apartment.
28
Wie funktioniert‘s? Zusammenfassung - Theading Model
“No ThreadingModel”-Objekte sind einfach zu implementieren, allerdings ist fast immer Marshalling notwendig. “ThreadingModel=Apartment”-Objekte verbessern die Performance mit relativ wenig Aufwand. “ThreadingModel=Free/Both”-Objekte haben die beste Performance, sind aber schwierig zu implementieren und zu debuggen.
29
Wie funktioniert‘s? Zusammenfassung - Objekt
Wenn das Threading Model auf Apartment “gesetzt” ist, dann muß der Zugriff auf globale Daten innerhalb von Objekt-Methoden grundsätzlich threadsafe erfolgen. critical sections Interlocked-functions Sollen die Objekte im MTA “laufen” müssen alle Operationen innerhalb des Objekts threadsafe sein.
30
Wie funktioniert‘s? Zusammenfassung - Client
Jeder Thread muß vor dem Benutzen von COM-Objekten CoInitialize(Ex) aufrufen. Thread “betritt” damit ein Apartment kein Marshalling bei gleichem Apartmenttyp! Schnittstellenzeiger dürfen niemals direkt an Threads in anderen Apartments übergeben werden. Marshalling zwischen unterschiedlichen Apartments!
31
Wie funktioniert‘s? Marshalling von Schnittstellenzeigern, I
Schnittstellenzeiger können zwischen Threads können nur dann direkt übergeben werden, wenn die Threads im gleichen Apartment “liegen”. Liegen die Threads in unterschiedlichen Appartments ist Marshalling erforderlich. CoMarshalInterThreadInterfaceInStream marshals an interface in one thread CoGetInterfaceAndReleaseStream unmarshals the interface in another
32
Wie funktioniert‘s? Marshalling von Schnittstellenzeigern, II
// The following global variable will hold the IStream pointer used by // both threads. COM makes sure the IStream pointer can be safely // used in different apartments. IStream* g_pStream; IMath* pMath; // Marshal the interface pointer in one thread. CoMarshalInterThreadInterfaceInStream (IID_IFace, pMath, g_pStream); . // Unmarshal it in another. CoGetInterfaceAndReleaseStream (g_pStream, IID_IFace, (void**) &pMath); Ein Stream nimmt immer nur einen Schnittstellenzeiger auf!
33
Wie funktioniert‘s? Free-Threaded Marshaller (FTM)
Der FTM ist ein COM-Objekt, das ein “custom marshalling” zur Verfügung stellt. Auf alle Objekte, die den FTM benutzen, kann grundsätzlich direkt zugegriffen werden “mehr Speed”, aber: hebelt Synchronisations-Mechanismen von COM komplett aus!
34
Wie funktioniert‘s? Free-Threaded Marshaller (FTM)
Objekte müssen threadsafe sein, um den FTM zu benutzen. Sofern “externe” Threads direkten Objekt-zugriff haben, kann COM die Zugriffe nicht synchronisieren! Der FTM sollte nicht von Objekten benutzt werden, die Objekte in anderen Apartments aufrufen. Callbacks können Deadlocks erzeugen Aufrufergebnis kann RPC_E_WRONG_THREAD sein
35
Allgemeine Hinweise Multi-Threading: RPC-Call, total blockierend
Single-Threading: Messageloop Deshalb: Kein UI mit MTA!!! In-proc-Server (DLLs) werden beim Beenden des Prozesses „entsorgt“!! Alternative: CoFreeUnusedLibraries oder CoFreeAllLibraries aufrufen OLE32.DLL: COM-Runtime OLEAUT32.DLL: Automation, Standard-Marshalling
36
Wo gibt’s weitere Info’s?
msdn online Microsoft Systems Journal diverse Artikel, z.B. Heft 4/1997 (!) Bücher von WROX Press Bücher von Microsoft Press Inside COM, Dale Rogerson Knowledge-Base-Artikel Q150777!!!
37
Fragen!? Uff...
Ähnliche Präsentationen
© 2024 SlidePlayer.org Inc.
All rights reserved.