Prozesse, Threads und Apartment
Ein Prozess ist eine Sammlung von virtuellem Arbeitsspeicher, Code, Daten und Systemressourcen. Ein Thread ist Code, der in einem Prozess seriell ausgeführt werden soll. Ein Prozessor führt Threads und keine Prozesse aus, sodass jede Anwendung über mindestens einen Prozess verfügt und ein Prozess immer über mindestens einen Ausführungsthread verfügt, der als primärer Thread bezeichnet wird. Ein Prozess kann über mehrere Threads zusätzlich zum primären Thread verfügen.
Prozesse kommunizieren über Nachrichten miteinander, indem sie die RPC-Technologie (Remote Procedure Call) von Microsoft verwenden, um Informationen untereinander zu übergeben. Es gibt keinen Unterschied für den Aufrufer zwischen einem Aufruf, der von einem Prozess auf einem Remotecomputer stammt, und einem Aufruf, der von einem anderen Prozess auf demselben Computer stammt.
Wenn ein Thread mit der Ausführung beginnt, wird er fortgesetzt, bis er abgebrochen oder von einem Thread mit höherer Priorität (durch eine Benutzeraktion oder den Threadplaner des Kernels) unterbrochen wird. Jeder Thread kann separate Codeabschnitte ausführen, oder mehrere Threads können denselben Codeabschnitt ausführen. Threads, die den gleichen Codeblock ausführen, verwalten separate Stapel. Jeder Thread in einem Prozess gibt die globalen Variablen und Ressourcen dieses Prozesses gemeinsam.
Der Threadplaner bestimmt anhand einer Kombination aus dem Prioritätsklassenattribut des Prozesses und der Basispriorität des Threads, wann und wie oft ein Thread ausgeführt werden soll. Sie legen das Prioritätsklassenattribut eines Prozesses fest, indem Sie die SetPriorityClass-Funktion aufrufen, und Sie legen die Basispriorität eines Threads mit einem Aufruf von SetThreadPriorityfest.
Multithreadanwendungen müssen zwei Threadingprobleme vermeiden: Deadlocks und Störungen. Ein Deadlock tritt auf, wenn jeder Thread darauf wartet, dass der andere etwas tut. Das COM-Aufrufsteuerelement hilft dabei, Deadlocks in Aufrufen zwischen Objekten zu verhindern. Eine Racebedingung tritt auf, wenn ein Thread vor einem anderen beendet wird, von dem er abhängt, wodurch ersterer einen nicht initialisierten Wert verwendet, da der zweite noch keinen gültigen wert bereitgestellt hat. COM stellt einige Funktionen bereit, die speziell entwickelt wurden, um Racebedingungen in Out-of-Process-Servern zu vermeiden. (Weitere Informationen finden Sie unter Out-of-Process Server Implementation Helpers.)
Apartment- und COM-Threadingarchitektur
Während COM das Modell mit einem einzelnen Thread pro Prozess unterstützt, das vor der Einführung mehrerer Ausführungsthreads weit verbreitet ist, können Sie Code schreiben, um die Vorteile mehrerer Threads zu nutzen, was zu effizienteren Anwendungen führt, indem Sie die Ausführung eines Threads zulassen, während ein anderer Thread auf den Abschluss eines zeitaufwändigen Vorgangs wartet.
Hinweis
Die Verwendung mehrerer Threads ist keine Garantie für eine bessere Leistung. Da thread factoring ein schwieriges Problem ist, führt die Verwendung mehrerer Threads häufig zu Leistungsproblemen. Der Schlüssel besteht darin, nur dann mehrere Threads zu verwenden, wenn Sie sicher sind, was Sie tun.
Im Allgemeinen besteht die einfachste Möglichkeit zum Anzeigen der COM-Threadingarchitektur darin, sich alle COM-Objekte im Prozess als in Gruppen unterteilt zu vorstellen, die als Apartment bezeichnet werden. Ein COM-Objekt befindet sich in genau einem Apartment, in dem Sinne, dass seine Methoden nur von einem Thread, der zu diesem Apartment gehört, direkt aufgerufen werden können. Jeder andere Thread, der das Objekt aufrufen möchte, muss einen Proxy durchlaufen.
Es gibt zwei Arten von Apartments: Singlethread-Apartmentsund Multithread-Apartments.
- Singlethread-Apartments bestehen aus genau einem Thread, sodass alle COM-Objekte, die sich in einem Singlethread-Apartment befinden, Nur-Methodenaufrufe von dem einen Thread empfangen können, der zu diesem Apartment gehört. Alle Methodenaufrufe an ein COM-Objekt in einem Singlethread-Apartment werden mit der Windows-Nachrichtenwarteschlange für den Thread des Singlethread-Apartments synchronisiert. Ein Prozess mit einem einzelnen Ausführungsthread ist einfach ein Sonderfall dieses Modells.
- Multithread-Apartments bestehen aus einem oder mehreren Threads, sodass alle COM-Objekte, die sich in einem Multithread-Apartment befinden, Methodenaufrufe direkt von allen Threads empfangen können, die zum Multithread-Apartment gehören. Threads in einem Multithread-Apartment verwenden ein Modell namens Freethreading. Aufrufe von COM-Objekten in einem Multithread-Apartment werden von den Objekten selbst synchronisiert.
Hinweis
Eine Beschreibung der Kommunikation zwischen Singlethread-Apartments und Multithread-Apartments innerhalb desselben Prozesses finden Sie unter Singlethread- und Multithreadkommunikation.
Ein Prozess kann 0 (null) oder mehr Singlethread-Apartments und 0 (null) oder ein Multithread-Apartment aufweisen.
In einem Prozess wird das Hauptapartment als erstes initialisiert. In einem Singlethreadprozess ist dies das einzige Apartment. Aufrufparameter werden zwischen Apartments gemarshallt, und COM übernimmt die Synchronisierung per Messaging. Wenn Sie mehrere Threads in einem Prozess als Freethreading festlegen, befinden sich alle freien Threads in einem einzelnen Apartment, Parameter werden direkt an jeden Thread im Apartment übergeben, und Sie müssen die gesamte Synchronisierung verarbeiten. In einem Prozess mit Freethreading und Apartmentthreading befinden sich alle freien Threads in einem einzelnen Apartment, und alle anderen Apartments sind Singlethread-Apartments. Ein Prozess, der COM-Arbeiten übernimmt, ist eine Sammlung von Apartments mit höchstens einem Multithread-Apartment, aber einer beliebigen Anzahl von Singlethread-Apartments.
Die Threadingmodelle in COM stellen den Mechanismus für Clients und Server bereit, die unterschiedliche Threadingarchitekturen verwenden, um zusammenzuarbeiten. Aufrufe zwischen Objekten mit unterschiedlichen Threadingmodellen in verschiedenen Prozessen werden natürlich unterstützt. Aus Der Perspektive des aufrufenden Objekts verhalten sich alle Aufrufe von Objekten außerhalb eines Prozesses identisch, unabhängig davon, wie das aufgerufene Objekt gethreadt wird. Ebenso verhalten sich eingehende Aufrufe aus sicht des aufgerufenen Objekts unabhängig vom Threadingmodell des Aufrufers identisch.
Die Interaktion zwischen einem Client und einem Out-of-Process-Objekt ist selbst dann einfach, wenn sie unterschiedliche Threadingmodelle verwenden, da sich Client und Objekt in unterschiedlichen Prozessen befinden. COM, das zwischen dem Client und dem Server ausgeführt wird, kann den Code für die Interoperabilität der Threadingmodelle bereitstellen, indem standardmäßiges Marshalling und RPC verwendet werden. Wenn beispielsweise ein Singlethreadobjekt gleichzeitig von mehreren Freethreadclients aufgerufen wird, werden die Aufrufe von COM synchronisiert, indem entsprechende Fenstermeldungen in der Nachrichtenwarteschlange des Servers platziert werden. Das Apartment des Objekts empfängt jedes Mal einen Anruf, wenn es Nachrichten abruft und verteilt. Es muss jedoch sorgfältig darauf geachtet werden, dass In-Process-Server ordnungsgemäß mit ihren Clients interagieren. (Weitere Informationen finden Sie unter In-Process Server Threading Issues.)
Das wichtigste Problem bei der Programmierung mit einem Multithreadmodell besteht darin, ihren Code threadsicher zu machen, sodass Nachrichten, die für einen bestimmten Thread vorgesehen sind, nur an diesen Thread gehen und der Zugriff auf Threads geschützt ist.
Weitere Informationen finden Sie unter den folgenden Themen: