2016-11-19 2 views
0

Wenn Sie ein COM-Objekt in der Running Object Table mit einem Null-Flag registrieren (eine schwache Ref anfragen), inkrementiert der ROT die Ref-Zählung um 1. Der Akt des Erhaltens eines Objekts aus dem ROT erhöht die Ref-Zählung um eins mehr. Sobald dieser frei ist, bleibt das Objekt mit einer Ref-Anzahl von mindestens eins am Leben. Seine Registrierung im ROT wird auch bei der Abfrage nicht magisch widerrufen.Wie implementiert die Tabelle laufender Objekte schwache Referenzen?

Wie ist das schwach? Wie unterscheidet sich das von einer starken Registrierung?

Die starke Registrierung folgt dem gleichen Muster - sowohl die Registrierung als auch der Abruf erhöhen die Ref-Zählung um eins.

Der Schnittstellenzeiger, den der ROT an In-Apartment-Clients zurückgibt, ist kein Proxy; Der ROT kann nicht wissen, dass ich meinen abgerufenen Schnittstellenzeiger freigegeben habe.

+0

Von [IRunningObjectTable :: Register] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms680747.aspx): * " Bei einer schwachen Registrierung (ROTFLAGS_REGISTRATIONKEEEPSALIVE nicht gesetzt) ​​gibt das ROT das Objekt immer dann frei, wenn die letzte starke Referenz auf das Objekt freigegeben wird.Für eine starke Registrierung (ROTFLAGS_REGISTRATIONKEEEPSALIVE) verhindert das ROT, dass das Objekt zerstört wird, bis die Registrierung des Objekts explizit erfolgt widerrufen. "* – IInspectable

+0

Ich habe das gelesen. Kannst du bitte erklären, was bedeutet "letzter starker Bezug auf das Objekt"? Wenn Sie es nur vom ROT bekommen und dann freigeben, wird das Objekt nicht freigegeben. Im schwachen Szenario hält der ROT genau wie im starken Fall eine Referenz. –

+0

Die Art und Weise, wie ich es verstehe (und ich muss zugeben, dass ich nie zusätzliche Prüfungen gemacht habe) ist, dass die Anfrage der starken Registrierung 'ROTFLAGS_REGISTRATIONKEEEPSALIVE' sicherstellt, dass ROT eine gültige Referenz enthält, egal was passiert. Ohne das Flag beginnt es auf ähnliche Weise (es gibt einfach keinen anderen Weg, insbesondere, dass die Dokumentation besagt, dass initial 'AddRef' immer passieren), aber die API behält sich das Recht vor, den Eintrag jederzeit zu veröffentlichen, insbesondere. bei bestimmten Ereignissen wie der Freigabe eines Proxys. –

Antwort

1

wirklich Entfernung von ROT Verhalten hängt nicht nur von ROTFLAGS_REGISTRATIONKEEPSALIVE Flagge, sondern auch sind (und wie) Ihr Objekt implementiert IExternalConnection

(besondere Note für @IInspectable nur - ja das alles nicht dokumentiert ist, nicht unterstützt, geändert kann - also bitte nicht mehr lesen).

Wenn wir Objekt in ROT-com registrieren immer Fragen Sie ihn für IExternalConnection Schnittstelle. wenn das Objekt nicht implementiert wurde, wurde die Standardimplementierung verwendet.

beiROTFLAGS_REGISTRATIONKEEPSALIVE bereits zum Zeitpunkt der Registrierung IExternalConnection::AddConnection genannt. also haben wir schon 1 externe Verbindung. ohne ROTFLAGS_REGISTRATIONKEEPSALIVE - diese Methode wird nicht aufgerufen.

jedes Mal, wenn jemand anrufen IRunningObjectTable::GetObject (! Von einer anderen Wohnung) die CRemoteUnknown::RemAddRef in unserem Prozess genannt. Dieser Methodenaufruf IExternalConnection::AddConnectionnur wenn wir registrieren ohneROTFLAGS_REGISTRATIONKEEPSALIVE Flag.

jedes Mal, wenn wir endgültig Release Objekt (auf Proxy, von früherem GetObject Anruf erhielt!) - CRemoteUnknown::RemReleaseWorker in unserem lokalen Prozess genannt. und es intern anrufen IExternalConnection::ReleaseConnectionnur im Fall keineROTFLAGS_REGISTRATIONKEEPSALIVE auf Objekt. Standard-Implementierung von IExternalConnection genannt CStdMarshal::Disconnect ->InternalIrotRevoke wenn externe Referenz (nicht Tottal Objektreferenz) erreichen 0 und fLastReleaseCloses == TRUE - als Ergebnis wird unser Objekt von ROT widerrufen. aber wenn wir IExternalConnection von selbst implementieren, können wir CoDisconnectObject anrufen oder nicht anrufen, damit wir von ROT widerrufen werden können oder nicht.

und schließlich, wenn wir direkt oder indirekt Anruf IRunningObjectTable::Revoke com Anruf IExternalConnection::ReleaseConnectionwenn wir registrieren mitROTFLAGS_REGISTRATIONKEEPSALIVE.

so Schlussfolgerung:

wenn wir registrieren mit ROTFLAGS_REGISTRATIONKEEPSALIVE - IExternalConnection::AddConnection wird nur einmal zum Zeitpunkt der Registrierung aufgerufen werden (. Wirklich genannt n+1 Zeit und n Zeit sagen werden kann - ReleaseConnection - aber das alles innerhalb IRunningObjectTable::Register Anruf) . wenn jemand unser Objekt von ROT bekommt - wir werden nicht benachrichtigt darüber. und schließlich wird IExternalConnection::ReleaseConnection auch nur einmal aufgerufen wenn wir IRunningObjectTable::Revoke anrufen.

von der anderen Seite, wenn wir nicht ROTFLAGS_REGISTRATIONKEEPSALIVE Flags verwenden - IExternalConnection Methoden werden nicht auf Register und Revoke genannt. aber es wird mehrere Zeit auf IRunningObjectTable::GetObject und endgültigen Release (auf Objekt Proxy) genannt werden. Wenn wir IExternalConnection nicht selbst implementieren oder CoDisconnectObject aufrufen, wenn externe Refs 0 und fLastReleaseCloses erreichen, werden wir aus ROT entfernt. aber wir frei nicht anrufenCoDisconnectObject (in diesem Fall wird Verhalten sein wie wir ROTFLAGS_REGISTRATIONKEEPSALIVE verwenden) oder sagen, rufen Sie es unter einer Bedingung.

Vorteil - wir können verfolgen alle unsere Object Verwendung im Fall keine ROTFLAGS_REGISTRATIONKEEPSALIVE Flag und selbst entscheiden, sind trennen müssen, wenn externe Refs erreichen 0 oder nicht.

und die letzte - wenn wir IRunningObjectTable::GetObject von der gleichen Wohnung anrufen, wo wir IRunningObjectTable::Register anrufen - haben wir nicht Proxy, sondern direkten Objektzeiger. in diesem Fall werden natürlich keine Aufrufe an IExternalConnection Methoden

+0

Jetzt macht es Sinn. Ich habe das Szenario mit einem Out-of-Apartment-Client getestet. Wenn die Verbindung getrennt wird, wird das Objekt bis auf Null freigegeben. –

+0

@SevaAlekseyev - ja, fundamental anders hier zwischen Out-of-Apartment-Client (wirklich Proxy) und In-Apartment-Clients. jedoch für die beste Verständnis-Situation - gut implementieren 'IExternalConnection' auf Self-Objekt (nur 2 einfache Methoden) und wird sehr klar danach – RbMm

Verwandte Themen