Prozesse, Threads und Apartments

Ein Prozess ist eine Sammlung von virtuellen Speicherplatz, 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 verfügt immer über mindestens einen Ausführungsthread, der als primärer Thread bezeichnet wird. Ein Prozess kann zusätzlich zum primären Thread über mehrere Threads verfügen.

Prozesse kommunizieren über Nachrichten miteinander, wobei die Remote Procedure Call (RPC)-Technologie von Microsoft verwendet wird, um Informationen aneinander zu übergeben. Es gibt keinen Unterschied für den Aufrufer zwischen einem Aufruf, der von einem Prozess auf einem Remotecomputer kommt, und einem Anruf, der von einem anderen Prozess auf demselben Computer kommt.

Wenn ein Thread mit der Ausführung beginnt, wird er fortgesetzt, bis er beendet wird oder bis er 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 denselben Codeblock ausführen, verwalten separate Stapel. Jeder Thread in einem Prozess teilt die globalen Variablen und Ressourcen dieses Prozesses.

Der Threadplaner bestimmt, wann und wie oft ein Thread ausgeführt werden soll, basierend auf einer Kombination aus dem Attribut der Prioritätsklasse des Prozesses und der Basispriorität des Threads. Sie legen das Prioritätsklassenattribut eines Prozesses fest, indem Sie die SetPriorityClass-Funktion aufrufen und die Basispriorität eines Threads mit einem Aufruf von SetThreadPriority festlegen.

Multithreadanwendungen müssen zwei Threadingprobleme vermeiden: Deadlocks und Races. 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ängig ist. Dies führt dazu, dass der erste Thread einen nicht initialisierten Wert verwendet, da dieser noch keinen gültigen bereitgestellt hat. COM bietet einige Funktionen, die speziell entwickelt wurden, um Racebedingungen auf Out-of-Process-Servern zu vermeiden. (Weitere Informationen finden Sie unter Out-of-Process-Serverimplementierungshilfsprogramme.)

Das Apartment und die COM-Threadingarchitektur

Com unterstützt zwar das Einzelthread-pro-Prozess-Modell, das vor der Einführung mehrerer Ausführungsthreads vorherrscht, aber Sie können Code schreiben, um die Vorteile mehrerer Threads zu nutzen, was zu effizienteren Anwendungen führt, indem ein Thread ausgeführt werden kann, während ein anderer Thread auf einen zeitaufwändigen Vorgang wartet.

Hinweis

Die Verwendung mehrerer Threads ist keine Garantie für eine bessere Leistung. Da thread factoring ein schwieriges Problem ist, verursacht die Verwendung mehrerer Threads häufig Leistungsprobleme. Der Schlüssel besteht darin, mehrere Threads nur zu verwenden, wenn Sie sehr 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 vorzustellen, die als Apartments bezeichnet werden. Ein COM-Objekt lebt in genau einer Wohnung, in dem Sinne, dass seine Methoden rechtlich nur von einem Thread, der zu dieser Wohnung 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 Wohnungen: Singlethread-Wohnungen und Multithread-Wohnungen.

  • Singlethread-Apartments bestehen aus genau einem Thread, sodass alle COM-Objekte, die sich in einem Singlethread-Apartment befinden, Methodenaufrufe nur 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 einem der Threads empfangen können, die zur Multithread-Wohnung gehören. Threads in einer Multithread-Wohnung verwenden ein Modell, das als Freethreading bezeichnet wird. Aufrufe von COM-Objekten in einem Multithread-Apartment werden von den -Objekten selbst synchronisiert.

Hinweis

Eine Beschreibung der Kommunikation zwischen Singlethread-Wohnungen und Multithread-Apartments innerhalb desselben Prozesses finden Sie unter Singlethread- und Multithread-Kommunikation.

 

Ein Prozess kann 0 oder mehr Singlethread-Wohnungen und null oder ein Multithread-Apartment enthalten.

In einem Prozess ist die Standard Wohnung die erste, die initialisiert wird. In einem Singlethread-Prozess ist dies die einzige Wohnung. Anrufparameter werden zwischen Wohnungen gemarshallt, und COM übernimmt die Synchronisierung über 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 in der Wohnung übergeben, und Sie müssen die gesamte Synchronisierung verarbeiten. In einem Prozess mit Free-Threading und Apartmentthreading befinden sich alle freien Threads in einer einzigen Wohnung und alle anderen Wohnungen sind Singlethread-Wohnungen. Ein Prozess, der COM funktioniert, ist eine Sammlung von Wohnungen mit höchstens einer Multithread-Wohnung, aber einer beliebigen Anzahl von Singlethread-Wohnungen.

Die Threadingmodelle in COM stellen den Mechanismus für Clients und Server bereit, die verschiedene Threadingarchitekturen verwenden, um zusammenzuarbeiten. Aufrufe zwischen Objekten mit unterschiedlichen Threadingmodellen in verschiedenen Prozessen werden natürlich unterstützt. Aus Sicht des aufrufenden Objekts verhalten sich alle Aufrufe von Objekten außerhalb eines Prozesses identisch, unabhängig davon, wie das aufgerufene Objekt im Thread ausgeführt wird. Ebenso verhalten sich eingehende Aufrufe aus der Perspektive des aufgerufenen Objekts identisch, unabhängig vom Threadingmodell des Aufrufers.

Die Interaktion zwischen einem Client und einem Out-of-Process-Objekt ist einfach, auch wenn sie unterschiedliche Threadingmodelle verwenden, da sich der Client und das Objekt in unterschiedlichen Prozessen befinden. COM, das zwischen Client und Server gespeichert ist, kann den Code für die Threadingmodelle bereitstellen, die interoperiert werden sollen, indem Standardmarsaling und RPC verwendet werden. Wenn beispielsweise ein Singlethreadobjekt gleichzeitig von mehreren Freethread-Clients aufgerufen wird, werden die Aufrufe von COM synchronisiert, indem entsprechende Fenstermeldungen in der Nachrichtenwarteschlange des Servers platziert werden. Die Wohnung des Objekts erhält bei jedem Abrufen und Senden von Nachrichten einen Aufruf. Es muss jedoch darauf geachtet werden, dass prozessinterne Server ordnungsgemäß mit ihren Clients interagieren. (Weitere Informationen finden Sie unter Probleme beim In-Process-Serverthreading.)

Das wichtigste Problem bei der Programmierung mit einem Multithreadmodell besteht darin, den Code threadsicher zu machen, sodass Nachrichten, die für einen bestimmten Thread vorgesehen sind, nur an diesen Thread gesendet werden und der Zugriff auf Threads geschützt ist.

Weitere Informationen finden Sie in den folgenden Themen: