Frage

Dies wird durch ausgelöst eine andere Frage.

Insbesondere habe ich eine in der Prozesscom -Klasse, die in der definiert ist CLSID -Register als ein ThreadingModel von Both.

Unser Prozess aktiviert dieses Objekt durch CoCreateInstance (nicht CoCreateInstanceEx, wenn das überhaupt für einen In-Proc-DLL-Server wichtig ist)

Bei einem Threading -Modell von Bothund angesichts der in der aufgeführten Regeln Dokumente:

Threading model of server | Apartment server is run in
------------------------------------------------------
Both                      | Same apartment as client

und angegeben, was Hans in der anderen Antwort schreibt:

... Marshaling tritt auf, wenn der Client -Anruf auf einem anderen Thread getätigt werden muss. ... kann passieren, wenn das im Comclass -Element angegebene ThreadingModel es erfordert. Mit anderen Worten, wenn das COM-Objekt in einem Thread erstellt wurde, aber auf einen anderen aufgerufen wurde und der Server nicht mit Thread-Sicherheit ist.

Meine vorläufige Schlussfolgerung wäre, dass ein solches Objekt wird noch nie Notwendigkeit implizite Marshalle von Aufrufen an seine Schnittstellen, da das Objekt immer in derselben Wohnung wie sein Kunde lebt.

Ist das richtig, auch wenn der Clientprozess ausgeführt wird Sta?

War es hilfreich?

Lösung

Ja, es kann Marshaling geben.

Wenn der Kunde Ihrer COM -Klasse in einem STA läuft und Sie versuchen, Ihre Klasse aus einer anderen Wohnung aufzurufen, muss er in die Wohnung, in der sie erstellt wurde, marschal marschal.

Die COM -Terminologie kann sehr verwirrend sein. Wenn Sie sich in diesem Fall auf einen "Client" beziehen, beziehen Sie sich wirklich auf einen Thread, nicht auf die gesamte Anwendung (wie dies impliziert wäre).

Both bedeutet nur, dass das Threading -Modell des Servers dem Client entspricht, der es instanziiert. Das heißt, wenn Sie Ihre Klasse instanziieren, nimmt es das Threading -Modell des Threads an, auf dem er erstellt wurde. Da Sie den Server in einem STA instanziieren, verwendet Ihr Server STA, was bedeutet, dass er nur auf dem Thread aufgerufen werden kann, der ihn erstellt hat. Wenn ein anderer Thread versucht, es aufzurufen, wird er zu dem Thread marschallt, auf dem er erstellt wurde.

Andere Tipps

Ich kann mir nicht helfen, dies zu posten, obwohl es keine direkte Antwort auf die Frage ist.

Es gibt einen brillanten MSKB -Artikel aus dem goldenen Alter von COM: Info: Beschreibungen und Arbeitsweise von OLE Threading -Modellen. Immer noch da und hat alle relevanten Informationen. Der Punkt ist, Sie sollten sich keine Sorgen darüber machen, ob es ein Marschall gibt oder nicht, wenn Sie die Regeln befolgen. Registrieren Sie einfach Ihr Objekt als ThreadingModel=Both, aggregieren Sie den freien Marschall mit CoCreateFreeThreadedMarshaler, und erledigt sein. COM wird bei Bedarf auf die bestmögliche Weise das Marshaling erledigen. Abhängig vom Apartmentmodell des Kunden kann der Client -Code den direkten Zeiger auf Ihre Schnittstelle empfangen, wenn er auch den Regeln folgt.

Jede "außerirdische" Schnittstelle, die Sie erhalten, wenn eine Methode Ihrer Schnittstelle aufgerufen wird, ist im Rahmen des Anrufs gültig, da Sie im selben Thread bleiben. Wenn Sie es nicht aufbewahren müssen, ist das alles, was zählt.

Wenn Sie jedoch die "Alien" -Kinterfläche zwischenspeichern müssen, wäre der richtige Weg, sie zu speichern CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStream:

Um es zu speichern:

  • Kritischen Abschnitt eingeben;
  • Anruf CoMarshalInterThreadInterfaceInStream und speichern die IStream Zeiger in einem Mitgliedsfeld;
  • Kritische Abschnitt verlassen;

Um es abzurufen

  • Kritischen Abschnitt eingeben;
  • Anruf CoGetInterfaceAndReleaseStream Um die Schnittstelle abzurufen
  • Anruf CoMarshalInterThreadInterfaceInStream und lagern Sie es erneut als IStream Für jede zukünftige Verwendung
  • Kritische Abschnitt verlassen;
  • Verwenden Sie die Schnittstelle im Bereich des aktuellen Aufrufs

Um es zu veröffentlichen:

  • Wenn Sie es nicht mehr behalten müssen, geben Sie einfach den gespeicherten frei IStream (innerhalb des kritischen Abschnitts).

Wenn das "Alien" -Objekt auch frei betrogen ist und die Dinge im selben Prozess geschehen, werden Sie sich wahrscheinlich mit einem direkten Schnittstellenzeiger befassen CoGetInterfaceAndReleaseStream. Sie sollten jedoch keine Annahmen treffen, und Sie müssen wirklich nicht wissen, ob das Objekt, mit dem Sie sich befassen, das ursprüngliche Objekt oder ein COM -Marshaller -Proxy ist.

Dies kann durch die Verwendung leicht optimiert werden CoMarshalInterface w/ MSHLFLAGS_TABLESTRONG / CoUnmarshalInterface / IStream::Seek(0, 0) / CoReleaseMarshalData Anstatt von CoGetInterfaceAndReleaseStream/CoGetInterfaceAndReleaseStream, zu unmarshal die gleiche Schnittstelle so oft wie nötig, ohne den Stream freizugeben.

Komplexere (und möglicherweise effizientere) Caching -Szenarien sind möglich, die lokale Speicher des Threads beinhalten. Ich glaube jedoch, dass das ein Überkleid sein würde. Ich habe kein Timing gemacht, aber ich denke, der Overhead von CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStreamist wirklich niedrig.

Das heißt, wenn Sie einen Staat beibehalten müssen Speichert Ressourcen oder Objekte, die möglicherweise eine Thread -Affinität erfordern, Anders als oben genannte COM -Schnittstellen, Sie sollte nicht Markieren Sie Ihr Objekt als ThreadingModel=Both oder aggregieren Sie die FTM.

Ja, Marshalle ist immer noch möglich. Ein paar Beispiele:

  1. Das Objekt wird aus einem MTA -Faden instanziiert und so in eine MTA -Wohnung eingebaut, und dann wird sein Zeiger in einen beliebigen STA -Faden übergeben und dass STA -Thread Methoden des Objekts aufruft. In diesem Fall kann ein STA -Thread nur über das Marshalling auf das Objekt zugreifen.

  2. Das Objekt wird aus einem STA -Faden instanziiert und so in eine STA -Wohnung zu diesem Faden gelegt und dann wird sein Zeiger in einen anderen STA -Faden oder einen MTA -Faden übergeben. In beiden Fällen können diese Threads nur über das Marshalling auf das Objekt zugreifen.

In der Tat können Sie in den folgenden zwei Fällen kein Marshalle nur erwarten:

  1. Das Objekt wird aus einem MTA -Thread instanziiert und dann nur von MTA -Threads zugegriffen - sowohl diejenige, die das Objekt instanziierte, als auch alle anderen MTA -Threads desselben Prozesses.
  2. Das Objekt wird aus einem STA -Thread instanziiert und dann nur von diesem Thread zugegriffen

und in allen anderen Fällen wird das Marshallowning eintreten.

ThreadingModel = Beide bedeutet einfach, dass der COM-Serverautor eine Garantie geben kann Sonstiges Der Code, den er nicht geschrieben hat, wird auf Thread-Safe-Weise angerufen. Der häufigste Fall bei der Ausführung solcher Fremdcode ist durch Rückrufe, wobei die Verbindungspunkte das häufigste Beispiel sind (normalerweise als "Ereignisse" in Kundenstupfen bezeichnet).

Wenn also die Serverinstanz in einem STA erstellt wurde, wird der Client -Programmierer erwarten, dass die Ereignisse auf demselben Thread ausgeführt werden. Auch wenn eine Servermethode, die ein solches Ereignis ausfeuert, aus einem anderen Thread aufgerufen wurde. Das erfordert, dass dieser Anruf marshalliert werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top