Freigeben über


Out-of-Process-Serverimplementierungshilfsprogramme

Vier Hilfsfunktionen, die von Out-of-Process-Servern aufgerufen werden können, stehen zur Vereinfachung des Schreibens von Servercode zur Verfügung. COM-Clients und COM-In-Process-Server würden sie in der Regel nicht aufrufen. Diese Funktionen dienen dazu, Rennbedingungen bei der Serveraktivierung zu verhindern, wenn die Server über mehrere Wohnungen oder mehrere Klassenobjekte verfügen. Sie können jedoch auch so einfach für Einzelthread- und Einzelklassenobjektserver verwendet werden. Die Funktionen sind wie folgt:

Um ordnungsgemäß herunterzufahren, muss ein COM-Server nachverfolgen, wie viele Objektinstanzen instanziiert wurden und wie oft die IClassFactory::LockServer-Methode aufgerufen wurde. Nur wenn diese beiden Zählungen null erreichen, kann ein Server heruntergefahren werden. In Single-Thread-COM-Servern wurde die Entscheidung zum Herunterfahren mit eingehenden Aktivierungsanforderungen koordiniert, die von der Nachrichtenwarteschlange serialisiert wurden. Wenn der Server eine Freigabe für die endgültige Objektinstanz erhält und sich für das Herunterfahren entscheidet, würden die Klassenobjekte widerrufen, bevor weitere Aktivierungsanforderungen verteilt wurden. Wenn nach diesem Punkt eine Aktivierungsanforderung eingegangen ist, würde COM erkennen, dass die Klassenobjekte widerrufen wurden und einen Fehler an den Dienststeuerungs-Manager (Service Control Manager, SCM) zurückgeben würden, was dann dazu führen würde, dass eine neue Instanz des lokalen Serverprozesses ausgeführt wird.

In einem Apartmentmodellserver, auf dem unterschiedliche Klassenobjekte auf verschiedenen Wohnungen registriert sind, und in allen Freithreadservern muss diese Entscheidung zum Herunterfahren mit Aktivierungsanforderungen über mehrere Threads koordiniert werden, sodass sich ein Thread des Servers nicht herunterfahren lässt, während ein anderer Thread des Servers ausgelastet ist, Klassenobjekte oder Objektinstanzen aushändigt. Ein klassischer, aber mühsamer Ansatz zur Lösung dieser Lösung besteht darin, den Server zu haben, nachdem er seine Klassenobjekte widerrufen hat, die Anzahl der Instanzen erneut zu überprüfen und aktiv zu bleiben, bis alle Instanzen freigegeben wurden.

Um serverautoren die Behandlung dieser Arten von Racebedingungen zu erleichtern, stellt COM zwei Referenzzählfunktionen bereit:

Wenn die globale Anzahl pro Prozessverweis null erreicht, ruft COM automatisch CoSuspendClassObjectsauf, wodurch verhindert wird, dass neue Aktivierungsanforderungen einsteigen. Der Server kann dann seine verschiedenen Klassenobjekte von seinen verschiedenen Threads zur Freizeit deregistern, ohne sich gedankenlos zu machen, dass eine weitere Aktivierungsanforderung eingehen kann. Alle neuen Aktivierungsanforderungen werden daher vom SCM beim Starten einer neuen Instanz des lokalen Serverprozesses behandelt.

Die einfachste Möglichkeit für eine lokale Serveranwendung, diese Funktionen zu verwenden, besteht darin, CoAddRefServerProcess im Konstruktor für jedes seiner Instanzobjekte und in jedem seiner IClassFactory::LockServer Methoden aufzurufen, wenn der fLock Parameter TRUEist. Die Serveranwendung sollte auch CoReleaseServerProcess im Destruktor der einzelnen Instanzobjekte und in jedem der IClassFactory::LockServer Methoden aufrufen, wenn der fLock Parameter FALSEist.

Schließlich sollte die Serveranwendung auf den Rückgabecode von CoReleaseServerProcessachten und wenn sie "0" zurückgibt, sollte die Serveranwendung die Bereinigung initiieren, was für einen Server mit mehreren Threads in der Regel bedeutet, dass die verschiedenen Threads signalisiert werden sollen, um ihre Nachrichtenschleifen zu beenden und CoAddRefServerProcess und CoReleaseServerProcessaufzurufen. Wenn die Serverprozesslebensdauer-Verwaltungsfunktionen verwendet werden, müssen sie sowohl in den Objektinstanzen als auch in der LockServer--Methode verwendet werden; andernfalls wird die Serveranwendung möglicherweise vorzeitig heruntergefahren.

Wenn eine CoGetClassObject Anforderung gestellt wird, kontaktiert COM den Server, marshallt die IClassFactory Schnittstelle des Klassenobjekts, kehrt zum Clientprozess zurück, hebt die IClassFactory Schnittstelle auf und gibt dies an den Client zurück. Zu diesem Zeitpunkt rufen Clients in der Regel LockServer- mit TRUE- auf, um zu verhindern, dass der Serverprozess heruntergefahren wird. Zwischen dem Marshalling des Klassenobjekts und dem Aufruf des Clients LockServer-, in dem ein anderer Client eine Verbindung mit demselben Server herstellen kann, eine Instanz abrufen und diese Instanz freigeben kann, wodurch der Server heruntergefahren und der erste Client hoch und trocken bleibt, mit einem getrennten IClassFactory Zeiger. Um diese Racebedingung zu verhindern, fügt COM dem Klassenobjekt einen impliziten Aufruf LockServer mit TRUE hinzu, wenn die IClassFactory-Schnittstelle und ein impliziter Aufruf von LockServer- mit FALSE-, wenn der Client die IClassFactory--Schnittstelle loslässt. Daher ist es nicht erforderlich, LockServer Aufrufe an den Server zurückzurufen, und der Proxy für LockServer einfach S_OK zurückgibt, ohne den Aufruf tatsächlich zu remoting.

Während der Initialisierung eines Out-of-Process-Serverprozesses gibt es eine weitere aktivierungsbezogene Racebedingung. Ein COM-Server, der mehrere Klassen registriert, ruft in der Regel CoRegisterClassObject mit REGCLS_LOCAL_SERVER für jede unterstützte CLSID auf. Nachdem dies für alle Klassen erfolgt ist, wechselt der Server in die Nachrichtenschleife. Bei einem COM-Server mit einem Thread werden alle Aktivierungsanforderungen blockiert, bis der Server die Nachrichtenschleife eingibt. Für einen Apartmentmodellserver, der unterschiedliche Klassenobjekte in verschiedenen Wohnungen registriert und für alle Freithreadserver, können Aktivierungsanforderungen jedoch früher als diese eingehen. Bei Apartmentmodellservern können Aktivierungsanforderungen eingehen, sobald ein Thread seine Nachrichtenschleife eingegeben hat. Bei Freithreadservern kann eine Aktivierungsanforderung eingehen, sobald das erste Klassenobjekt registriert ist. Da eine Aktivierung dieses frühen Zeitpunkts auftreten kann, ist es auch möglich, dass die endgültige Version eintritt (und daher dazu führt, dass der Server heruntergefahren wird), bevor der Rest des Servers die Möglichkeit hatte, die Initialisierung abzuschließen.

Um diese Racebedingungen zu beseitigen und den Auftrag des Server-Writers zu vereinfachen, sollte jeder Server, der mehrere Klassenobjekte bei COM registrieren möchte, CoRegisterClassObject- mit REGCLS_LOCAL_SERVER aufrufen | REGCLS_SUSPENDED für jede unterschiedliche CLSID, die der Server unterstützt. Nachdem alle Klassen registriert wurden und der Serverprozess bereit ist, eingehende Aktivierungsanforderungen zu akzeptieren, sollte der Server einen Aufruf an CoResumeClassObjects. Diese Funktion weist COM an, den SCM über alle registrierten Klassen zu informieren, und es beginnt, Aktivierungsanforderungen in den Serverprozess zu übertragen. Die Verwendung dieser Funktionen bietet die folgenden Vorteile:

  • Es wird nur ein Aufruf an den SCM durchgeführt, unabhängig davon, wie viele CLSIDs registriert sind, wodurch die Gesamtregistrierungszeit (und damit die Startzeit der Serveranwendung) reduziert wird.
  • Wenn der Server über mehrere Wohnungen und unterschiedliche CLSIDs verfügt, in verschiedenen Wohnungen registriert sind oder der Server ein Freithreadserver ist, werden keine Aktivierungsanforderungen eingehen, bis der Server CoResumeClassObjectsaufruft, sodass der Server die Möglichkeit hat, alle clSIDs zu registrieren und ordnungsgemäß einzurichten, bevor er Aktivierungsanforderungen behandeln und mögliche Herunterfahren von Anforderungen durchführen muss.

COM Server-Verantwortlichkeiten