1

当您在运行对象表中注册带有零标志的 COM 对象(请求弱引用)时,ROT 将引用计数增加 1。从 ROT 获取对象的行为将引用计数再增加一。一旦该对象被释放,该对象将保持活动状态,并且引用计数至少为 1。它在 ROT 中的注册也不会在检索时被神奇地撤销。

怎么这么弱?这与强注册有何不同?

强注册遵循相同的模式——注册和检索都将引用计数增加一。

ROT返回给公寓内客户端的接口指针不是代理;ROT 无法知道我已经释放了检索到的接口指针。

4

1 回答 1

2

真正从 ROT 行为中移除不仅取决于ROTFLAGS_REGISTRATIONKEEPSALIVE标志,还取决于(以及如何)您的对象实现IExternalConnection

仅针对 @IInspectable 的特别说明 - 是的,所有这些都没有记录,不受支持,可以更改 - 所以请不要阅读更多内容)。

当我们在 ROT com 中注册对象时,总是向他查询IExternalConnection接口。如果对象没有实现它 - 使用默认实现。

如果 ROTFLAGS_REGISTRATIONKEEPSALIVE已经在注册时间IExternalConnection::AddConnection调用。所以我们已经有 1 个外部连接。without ROTFLAGS_REGISTRATIONKEEPSALIVE- 未调用此方法。

每次有人打电话IRunningObjectTable::GetObject!从另一间公寓CRemoteUnknown::RemAddRef在我们的过程中被调用。仅当我们在没有标志的情况下注册时才调用此方法。IExternalConnection::AddConnection ROTFLAGS_REGISTRATIONKEEPSALIVE

每次我们最终的Release对象(!on proxy,从先前的GetObject调用中获得) -CRemoteUnknown::RemReleaseWorker在我们的本地进程中调用。并且它 没有对象的情况下在内部调用。调用的默认实现->当外部引用(不是总对象引用)达到 0 并且- 结果我们的对象从 ROT 中撤销。但是如果我们自己实现,我们可以调用或不调用,因此我们可以被撤销或不被 ROT 撤销。IExternalConnection::ReleaseConnection ROTFLAGS_REGISTRATIONKEEPSALIVEIExternalConnectionCStdMarshal::DisconnectInternalIrotRevokefLastReleaseCloses == TRUEIExternalConnectionCoDisconnectObject

最后,当我们直接或间接调用IRunningObjectTable::Revokecom 时如果我们注册.IExternalConnection::ReleaseConnection ROTFLAGS_REGISTRATIONKEEPSALIVE

所以结论:

如果我们注册ROTFLAGS_REGISTRATIONKEEPSALIVE-IExternalConnection::AddConnection将在注册时只被调用一次(真的可以称为n+1时间和n时间ReleaseConnection- 但所有这些都在内部IRunningObjectTable::Register调用。)。当有人从 ROT 获取我们的对象时 - 我们不会收到通知。当我们调用时, finallyIExternalConnection::ReleaseConnection也只会被调用一次IRunningObjectTable::Revoke

另一方面,如果我们不使用ROTFLAGS_REGISTRATIONKEEPSALIVE标志 -方法IExternalConnection不会被调用Registerand 。Revoke但它将被多次调用IRunningObjectTable::GetObject和最终Release在对象代理上)。如果我们没有IExternalConnection自己实现或CoDisconnectObject在外部引用达到 0 时调用fLastReleaseCloses- 我们将从 ROT 中删除。但是我们自由不调用 CoDisconnectObject(在这种情况下,行为就像我们使用的那样ROTFLAGS_REGISTRATIONKEEPSALIVE)或者说在某些条件下调用它。

优势 - 我们可以跟踪我们的每个对象的使用,以防没有ROTFLAGS_REGISTRATIONKEEPSALIVE标志并自行决定是否需要在外部 refs 达到 0 时断开连接。

最后一个——如果我们从我们呼叫 IRunningObjectTable::GetObject的同一个公寓呼叫IRunningObjectTable::Register——我们得到的不是代理,而是直接对象指针。在这种情况下,当然不会调用IExternalConnection方法

于 2016-11-20T13:23:09.420 回答