[英]Can I use weak references as instance variables in Windows RT/8?
[英]How does Running Object Table implement weak references?
當您在運行對象表中用零標志注冊COM對象(請求弱引用)時,ROT將引用計數增加1。從ROT獲取對象的動作會使引用計數再增加一。 一旦釋放了該對象,該對象就保持活動狀態,且引用計數至少為1。 檢索后,它在ROT中的注冊也不會被魔術撤銷。
那怎么弱? 這與強勢注冊有何不同?
強注冊遵循相同的模式-注冊和檢索都將引用計數加1。
ROT返回給公寓內客戶端的接口指針不是代理。 ROT無法知道我已釋放檢索到的接口指針。
真正擺脫ROT行為不僅取決於ROTFLAGS_REGISTRATIONKEEPSALIVE
標志,而且取決於對象實現IExternalConnection
(以及如何實現)
( 僅針對@IInspectable的特殊說明-是的,所有這些都是未記錄的,不受支持的,可以更改-因此請不要繼續閱讀 )。
當我們在ROT com中注冊對象時,總是向他查詢IExternalConnection
接口。 如果對象未實現,則使用默認實現。
萬一 ROTFLAGS_REGISTRATIONKEEPSALIVE
已經在注冊時IExternalConnection::AddConnection
調用。 因此我們已經有1個外部連接。 沒有ROTFLAGS_REGISTRATIONKEEPSALIVE
不調用此方法。
每次有人調用IRunningObjectTable::GetObject
( !從另一個公寓 )時,在我們的過程中調用CRemoteUnknown::RemAddRef
。 僅當我們注冊時未帶 ROTFLAGS_REGISTRATIONKEEPSALIVE
標志時,此方法才調用IExternalConnection::AddConnection
。
每次當我們最終Release
對象( !on代理,從先前的GetObject
調用獲得 )時-在本地過程中調用 CRemoteUnknown::RemReleaseWorker
。 並且僅在對象上沒有 ROTFLAGS_REGISTRATIONKEEPSALIVE
情況下才內部調用IExternalConnection::ReleaseConnection
ROTFLAGS_REGISTRATIONKEEPSALIVE
。 當外部參考(不是全部對象參考)達到0並且fLastReleaseCloses == TRUE
時, IExternalConnection
默認實現稱為CStdMarshal::Disconnect
> InternalIrotRevoke
結果我們的對象已從ROT撤消。 但是,如果我們自行實現IExternalConnection
,則可以調用或不調用CoDisconnectObject
因此可以從ROT撤消或不撤消。
最后, 如果我們向 ROTFLAGS_REGISTRATIONKEEPSALIVE
注冊, 則直接或間接調用IRunningObjectTable::Revoke
com調用IExternalConnection::ReleaseConnection
ROTFLAGS_REGISTRATIONKEEPSALIVE
。
這樣的結論:
如果我們用注冊ROTFLAGS_REGISTRATIONKEEPSALIVE
- IExternalConnection::AddConnection
將在注冊時只調用一次(真可謂說n+1
的時間和n
時間- ReleaseConnection
-但這里面所有IRunningObjectTable::Register
。調用)。 當有人從ROT獲取我們的對象時-我們將不會收到通知 。 最后,當我們調用IRunningObjectTable::Revoke
時, IExternalConnection::ReleaseConnection
IRunningObjectTable::Revoke
也將僅被調用一次。
另一方面,如果我們不使用ROTFLAGS_REGISTRATIONKEEPSALIVE
標志-將不會在Register
and Revoke
上調用 IExternalConnection
方法。 但是將在IRunningObjectTable::GetObject
和最終Release
( 在對象代理 ) 上 多次調用 。 如果我們自己沒有實現IExternalConnection
或在外部引用達到0和fLastReleaseCloses
時調用CoDisconnectObject
我們將從ROT中刪除。 但是我們不會隨意調用 CoDisconnectObject
(在這種情況下,行為就像我們使用ROTFLAGS_REGISTRATIONKEEPSALIVE
),或者說在某種情況下調用它。
優勢-如果沒有ROTFLAGS_REGISTRATIONKEEPSALIVE
標志,我們可以跟蹤每個對象的使用情況,並自行決定是否在外部引用達到0時斷開連接。
最后一個-如果我們在調用IRunningObjectTable::Register
同一單元中調用IRunningObjectTable::GetObject
,則不是代理,而是直接對象指針。 在這種情況下,當然不會調用IExternalConnection
方法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.