In-Process Serverthreadingprobleme

Ein Prozessserver ruft coInitialize, CoInitializeExoder OleInitialize nicht auf, um sein Threadingmodell zu markieren. Für threadfähige DLL-basierte oder prozessbezogene Objekte müssen Sie das Threadingmodell in der Registrierung festlegen. Das Standardmodell, wenn Sie kein Threadingmodell angeben, ist Singlethread pro Prozess. Um ein Modell anzugeben, fügen Sie den ThreadingModel-Wert dem InprocServer32-Schlüssel in der Registrierung hinzu.

DLLs, die die Instanziierung eines Klassenobjekts unterstützen, müssen die Funktionen DllGetClassObject und DllCanUnloadNowimplementieren und exportieren. Wenn ein Client eine Instanz der Von der DLL unterstützten Klasse möchte, ruft ein Aufruf von CoGetClassObject (entweder direkt oder durch einen Aufruf von CoCreateInstance) DllGetClassObject auf, um einen Zeiger auf sein Klassenobjekt abzurufen, wenn das Objekt in einer DLL implementiert wird. DllGetClassObject sollte daher in der Lage sein, mehrere Klassenobjekte oder ein einzelnes threadsicheres Objekt zu verschenken (im Wesentlichen nur mit InterlockedIncrement / InterlockedDecrement für die interne Verweisanzahl).

Wie der Name schon sagt, wird DllCanUnloadNow aufgerufen, um zu bestimmen, ob die DLL, die sie implementiert, verwendet wird, sodass der Aufrufer sie sicher entladen kann, wenn dies nicht der Name ist. Aufrufe von CoFreeUnusedLibraries aus einem beliebigen Thread leiten immer durch den Thread des Hauptapartments, um DllCanUnloadNow aufzurufen.

Wie andere Server können In-Process-Server Singlethread-, Apartmentthread- oder Freethreadserver sein. Diese Server können von jedem OLE-Client verwendet werden, unabhängig vom threadingmodell, das von diesem Client verwendet wird.

Alle Kombinationen der Interoperabilität des Threadingmodells sind zwischen Clients und In-Process-Objekten zulässig. Die Interaktion zwischen einem Client und einem In-Process-Objekt, das verschiedene Threadingmodelle verwendet, entspricht genau der Interaktion zwischen Clients und Out-of-Process-Servern. Wenn sich das Threadingmodell des Clients und des In-Process-Servers für einen Prozessserver unterscheidet, muss COM sich selbst zwischen dem Client und dem Objekt zusammensetzen.

Wenn ein Prozessobjekt, das das Singlethreadmodell unterstützt, gleichzeitig von mehreren Threads eines Clients aufgerufen wird, kann COM den Clientthreads nicht erlauben, direkt auf die Schnittstelle des Objekts zuzugreifen. "Das Objekt wurde nicht für diesen Zugriff entworfen. Stattdessen muss COM sicherstellen, dass Aufrufe synchronisiert werden und nur vom Clientthread ausgeführt werden, der das Objekt erstellt hat. Aus diesem Grund erstellt COM das Objekt im Hauptapartment des Clients und erfordert, dass alle anderen Clientpartments mithilfe von Proxys auf das Objekt zugreifen.

Wenn ein Freethread-Apartment (Multithread-Apartmentmodell) in einem Client einen Apartmentthread-In-Process-Server erstellt, erstellt COM einen Singlethread-Apartmentmodell-Hostthread im Client. Dieser Hostthread erstellt das -Objekt, und der Schnittstellenzeiger wird zurück zum Freethread-Apartment des Clients gemarshallt. Wenn ein Singlethread-Apartment in einem Apartmentmodellclient einen Prozessserver mit Freethreading erstellt, startet COM einen Freethreadhostthread (Multithread-Apartment, auf dem das Objekt erstellt und dann wieder an das Singlethread-Apartment des Clients gemarshallt wird).

Hinweis

Wenn Sie eine benutzerdefinierte Schnittstelle auf einem In-Process-Server entwerfen, sollten Sie im Allgemeinen auch den Marshallingcode dafür bereitstellen, damit COM die Schnittstelle zwischen Client-Apartments marshallen kann.

COM schützt den Zugriff auf Objekte, die von einer Singlethread-DLL bereitgestellt werden, indem der Zugriff aus demselben Clientapartment erforderlich ist, in dem sie erstellt wurden. Darüber hinaus sollte auf alle DLL-Einstiegspunkte (z. B. DllGetClassObject und DllCanUnloadNow)und globale Daten immer vom gleichen Apartment zugegriffen werden. COM erstellt solche Objekte im Hauptapartment des Clients und ermöglicht dem Hauptapartment direkten Zugriff auf die Zeiger des Objekts. Aufrufe aus den anderen Apartments verwenden Interthread-Marshalling, um vom Proxy zum Stub im Hauptapartment und dann zum Objekt zu wechseln. Dadurch kann COM Aufrufe des -Objekts synchronisieren. Interthreadaufrufe sind langsam, daher wird empfohlen, diese Server neu zu schreiben, um mehrere Apartments zu unterstützen.

Wie bei einem Singlethread-In-Process-Server muss dasselbe Clientapartment, aus dem es erstellt wurde, auf ein Objekt zugreifen, das von einer Apartmentmodell-DLL bereitgestellt wird. Die von diesem Server bereitgestellten Objekte können jedoch in mehreren Apartments des Clients erstellt werden, sodass der Server seine Einstiegspunkte (z. B. DllGetClassObject und DllCanUnloadNow)für die Multithreadverwendung implementieren muss. Wenn beispielsweise zwei Apartments eines Clients versuchen, zwei Instanzen des In-Process-Objekts gleichzeitig zu erstellen, kann DllGetClassObject gleichzeitig von beiden Apartments aufgerufen werden. DllCanUnloadNow muss geschrieben werden, damit die DLL nicht entladen wird, während der Code noch in der DLL ausgeführt wird.

Wenn die DLL nur eine Instanz der Klassenfactory bereitstellt, um alle Objekte zu erstellen, muss die Implementierung der Klassenfactory auch für die Verwendung mit Multithread entworfen werden, da auf sie von mehreren Clientpartments zugegriffen wird. Wenn die DLL bei jedem Aufruf von DllGetClassObject eine neue Instanz der Klassenfactory erstellt, muss die Klassenfactory nicht threadsicher sein.

Von der Klassenfactory erstellte Objekte müssen nicht threadsicher sein. Nach der Erstellung durch einen Thread erfolgt der Zugriff auf das Objekt immer über diesen Thread, und alle Aufrufe des Objekts werden von COM synchronisiert. Das Apartmentmodell-Apartment eines Clients, der dieses Objekt erstellt, erhält einen direkten Zeiger auf das Objekt. Clientpartments, die sich von dem Apartment unterscheiden, in dem das Objekt erstellt wurde, müssen über Proxys auf das Objekt zugreifen. Diese Proxys werden erstellt, wenn der Client die Schnittstelle zwischen seinen Apartments marshallt.

Wenn ein Prozess-DLL-ThreadingModel-Wert auf "Both" festgelegt ist, kann ein von dieser DLL bereitgestelltes Objekt direkt (ohne Proxy) in Singlethread- oder Multithreadclient-Apartments erstellt und verwendet werden. Sie kann jedoch nur direkt innerhalb des Apartments verwendet werden, in dem sie erstellt wurde. Um das Objekt einem anderen Apartment zuzuweisen, muss das Objekt gemarshallt werden. Das DLL-Objekt muss eine eigene Synchronisierung implementieren und kann von mehreren Clientappartes gleichzeitig aufgerufen werden.

Com stellt die CoCreateFreeThreadedMarshaler-Funktion bereit, um die Leistung für den Freithreadzugriff auf prozessinterne DLL-Objekte zu beschleunigen. Diese Funktion erstellt ein Freethread-Marshallingobjekt, das mit einem Prozessserverobjekt aggregiert werden kann. Wenn ein Clientapartment im gleichen Prozess Zugriff auf ein Objekt in einem anderen Apartment benötigt, stellt das Aggregieren des Freethread-Marshallers dem Client einen direkten Zeiger auf das Serverobjekt und nicht auf einen Proxy bereit, wenn der Client die Schnittstelle des Objekts zu einem anderen Apartment marshallt. Der Client muss keine Synchronisierung durchführen. Dies funktioniert nur innerhalb desselben Prozesses. Standard-Marshalling wird für einen Verweis auf das Objekt verwendet, das an einen anderen Prozess gesendet wird.

Ein Objekt, das von einer Prozess-DLL bereitgestellt wird, die nur freies Threading unterstützt, ist ein Freethread-Objekt. Es implementiert eine eigene Synchronisierung und kann von mehreren Clientthreads gleichzeitig aufgerufen werden. Dieser Server marshallt keine Schnittstellen zwischen Threads, sodass dieser Server direkt (ohne Proxy) nur von Multithread-Apartments in einem Client erstellt und verwendet werden kann. Singlethread-Apartments, die es erstellen, greifen über einen Proxy darauf zu.

Zugreifen auf Schnittstellen zwischen Apartments

Auswählen des Threadingmodells

Multithread-Apartment

Prozesse, Threads und Apartment

Singlethread- und Multithreadkommunikation

Singlethread-Apartment