Freigeben über


Multithreaded Apartments

In einem Multithread-Apartmentmodell befinden sich alle Threads im Prozess, die als Freithreads initialisiert wurden, in einer einzigen Wohnung. Daher ist es nicht erforderlich, zwischen Threads zu marshallen. Die Threads müssen keine Nachrichten abrufen und verteilen, da COM keine Fenstermeldungen in diesem Modell verwendet.

Aufrufe von Objekten in der Multithread-Wohnung können auf jedem Thread in der Wohnung ausgeführt werden. Es gibt keine Serialisierung von Anrufen; viele Aufrufe können für dieselbe Methode oder für dasselbe Objekt gleichzeitig auftreten. Objekte, die in der Multithread-Wohnung erstellt wurden, müssen jederzeit in der Lage sein, Aufrufe ihrer Methoden aus anderen Threads zu verarbeiten.

Da Aufrufe von Objekten in keiner Weise serialisiert werden, bietet multithreaded object concurrency die höchste Leistung und nutzt den besten Vorteil der Multiprozessorhardware für threadübergreifende, prozessübergreifende und computerübergreifende Aufrufe. Dies bedeutet jedoch, dass der Code für Objekte die Synchronisierung in ihren Schnittstellenimplementierungen bereitstellen muss, in der Regel durch die Verwendung von Synchronisierungsgrundtypen wie Ereignisobjekten, kritischen Abschnitten, Mutexen oder Semaphoren, die weiter unten in diesem Abschnitt beschrieben werden. Da das Objekt nicht die Lebensdauer der Threads steuert, auf die zugegriffen wird, kann kein threadspezifischer Zustand im Objekt gespeichert werden (im lokalen Threadspeicher).

Im Folgenden finden Sie einige wichtige Überlegungen zur Synchronisierung für Multithread-Wohnungen:

  • COM stellt nur die Anrufsynchronisierung für Singlethread-Wohnungen bereit.
  • Multithread-Wohnungen empfangen keine Anrufe beim Tätigen von Anrufen (im selben Thread).
  • Multithread-Wohnungen können keine eingabesynchronen Anrufe tätigen.
  • Asynchrone Aufrufe werden in synchrone Aufrufe in Multithread-Apartments konvertiert.
  • Der Nachrichtenfilter wird nicht für einen Thread in einer Multithread-Wohnung aufgerufen.

Um einen Thread als Freithread zu initialisieren, rufen Sie CoInitializeEx-auf, wobei COINIT_MULTITHREADED angegeben wird. Informationen zum In-Process-Serverthreading finden Sie unter In-Process Serverthreading-Probleme.

Mehrere Clients können gleichzeitig ein Objekt aufrufen, das freithreading unterstützt. In Freethread-Out-of-Process-Servern erstellt COM über das RPC-Subsystem einen Pool von Threads im Serverprozess, und ein Clientaufruf (oder mehrere Clientaufrufe) kann jederzeit von jedem dieser Threads übermittelt werden. Ein Out-of-Process-Server muss auch die Synchronisierung in seiner Klassenfactory implementieren. Freithreads, In-Process-Objekte können direkte Aufrufe von mehreren Threads des Clients empfangen.

Der Client kann COM in mehreren Threads ausführen. Alle Threads gehören zu derselben Multithread-Wohnung. Schnittstellenzeiger werden direkt von Thread zu Thread in einem Multithread-Apartment übergeben, sodass Schnittstellenzeiger nicht zwischen den Threads gemarstet werden. Nachrichtenfilter (Implementierungen von IMessageFilter) werden in Multithread-Wohnungen nicht verwendet. Der Clientthread wird angehalten, wenn ein COM-Aufruf an Out-of-Apartment-Objekte ausgeführt wird und fortgesetzt wird, wenn der Aufruf zurückgegeben wird. Aufrufe zwischen Prozessen werden weiterhin von RPC verarbeitet.

Threads, die mit dem Freithreadmodell initialisiert werden, müssen ihre eigene Synchronisierung implementieren. Wie weiter oben in diesem Abschnitt erwähnt, ermöglicht Windows diese Implementierung über die folgenden Synchronisierungsgrundtypen:

  • Ereignisobjekte bieten eine Möglichkeit, einen oder mehrere Threads zu signalisieren, dass ein Ereignis aufgetreten ist. Jeder Thread in einem Prozess kann ein Ereignisobjekt erstellen. Ein Handle für das Ereignis wird von der Ereigniserstellungsfunktion CreateEventzurückgegeben. Nachdem ein Ereignisobjekt erstellt wurde, können Threads mit einem Handle für das Objekt darauf warten, bevor die Ausführung fortgesetzt wird.
  • Kritische Abschnitte werden für einen Codeabschnitt verwendet, der exklusiven Zugriff auf einige freigegebene Daten erfordert, bevor sie ausgeführt werden kann und die nur von den Threads innerhalb eines einzelnen Prozesses verwendet wird. Ein kritischer Abschnitt ist wie ein Drehkreuz, durch den jeweils nur ein Thread übergeben werden kann, der wie folgt funktioniert:
    • Um sicherzustellen, dass nicht mehr als ein Thread gleichzeitig auf freigegebene Daten zugreift, weist der primäre Thread eines Prozesses eine globale CRITICAL_SECTION Datenstruktur zu und initialisiert seine Member. Ein Thread, der einen kritischen Abschnitt eingibt, ruft die EnterCriticalSection-Funktion auf und ändert die Elemente der Datenstruktur.
    • Ein Thread, der versucht, einen kritischen Abschnitt einzugeben, ruft EnterCriticalSection auf, um festzustellen, ob die CRITICAL_SECTION Datenstruktur geändert wurde. Wenn ja, befindet sich derzeit ein anderer Thread im kritischen Abschnitt, und der nachfolgende Thread wird in den Ruhezustand versetzt. Ein Thread, der einen kritischen Abschnitt verlässt, ruft LeaveCriticalSectionauf, wodurch die Datenstruktur zurückgesetzt wird. Wenn ein Thread einen kritischen Abschnitt verlässt, aktiviert das System einen der schlafenden Threads, der dann in den kritischen Abschnitt wechselt.
  • Mutexes führt dieselbe Funktion wie ein kritischer Abschnitt aus, mit der Ausnahme, dass der Mutex für Threads zugänglich ist, die in verschiedenen Prozessen ausgeführt werden. Das Besitzen eines Mutex-Objekts ist wie das Wort in einer Debatte. Ein Prozess erstellt ein Mutex-Objekt, indem die CreateMutex--Funktion aufgerufen wird, die ein Handle zurückgibt. Der erste Thread, der ein Mutex-Objekt anfordert, erhält den Besitz davon. Wenn der Thread mit dem Mutex fertig ist, übergibt der Besitz an andere Threads, die zuerst bereitgestellt werden.
  • Semaphoren werden verwendet, um eine Referenzanzahl für einige verfügbare Ressourcen aufrechtzuerhalten. Ein Thread erstellt ein Semaphor für eine Ressource, indem die CreateSemaphore--Funktion aufgerufen und ein Zeiger auf die Ressource, eine anfängliche Ressourcenanzahl und die maximale Ressourcenanzahl übergeben wird. Diese Funktion gibt ein Handle zurück. Ein Thread, der eine Ressource anfordert, übergibt seinen Semaphorhandle-Handle in einem Aufruf der WaitForSingleObject--Funktion. Das Semaphor-Objekt fragt die Ressource ab, um festzustellen, ob es verfügbar ist. Wenn ja, erhöht der Semaphor die Ressourcenanzahl und reaktiviert den Wartethread. Wenn die Anzahl null ist, bleibt der Thread einschlafen, bis ein anderer Thread eine Ressource loslässt, wodurch der Semaphor die Anzahl auf eine erhöht.

Zugriff auf Schnittstellen über Wohnungen

Auswählen des Threadingmodells

In-Process Serverthreadingprobleme

Prozesse, Threads und Apartments

Single-Threaded und Multithread-Kommunikation

Single-Threaded Apartments