當您在運行對象表中註冊一個帶有零標誌的COM對象(請求弱引用)時,ROT會將引用計數遞增1.從ROT獲取對象的行爲會將引用計數再增加一個。一旦釋放了該對象,該對象就會保持活動狀態,並且引用計數至少爲1。它在ROT中的註冊也不會在檢索時被神奇地撤銷。運行對象表如何實現弱引用?
這是如何弱?與強大的註冊有什麼不同?
強註冊遵循相同的模式 - 註冊和檢索增加一個參考計數。
ROT返回到in-apartment客戶端的接口指針不是代理; ROT無法知道我釋放了我檢索到的接口指針。
當您在運行對象表中註冊一個帶有零標誌的COM對象(請求弱引用)時,ROT會將引用計數遞增1.從ROT獲取對象的行爲會將引用計數再增加一個。一旦釋放了該對象,該對象就會保持活動狀態,並且引用計數至少爲1。它在ROT中的註冊也不會在檢索時被神奇地撤銷。運行對象表如何實現弱引用?
這是如何弱?與強大的註冊有什麼不同?
強註冊遵循相同的模式 - 註冊和檢索增加一個參考計數。
ROT返回到in-apartment客戶端的接口指針不是代理; 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
對象(的代理,從以前的GetObject
通話獲得!) - CRemoteUnknown::RemReleaseWorker
叫在我們當地的過程。它在內部呼叫IExternalConnection::ReleaseConnection
只有的情況下沒有ROTFLAGS_REGISTRATIONKEEPSALIVE
對象。 IExternalConnection
的默認實現調用CStdMarshal::Disconnect
- >InternalIrotRevoke
當外部參考(非tottal對象引用)達到0和fLastReleaseCloses == TRUE
- 結果我們的對象從ROT被撤銷。但如果我們自己實施IExternalConnection
,我們可以打電話或不打電話CoDisconnectObject
,所以我們可以從ROT撤銷。
最後當我們直接或間接調用IRunningObjectTable::Revoke
COM調用IExternalConnection::ReleaseConnection
如果我們註冊與ROTFLAGS_REGISTRATIONKEEPSALIVE
。
這樣的結論:如果我們用ROTFLAGS_REGISTRATIONKEEPSALIVE
註冊
- IExternalConnection::AddConnection
將在註冊時只調用一次(真可謂說n+1
時間和n
時間 - ReleaseConnection
- 但這裏面所有IRunningObjectTable::Register
調用) 。當有人從ROT得到我們的對象 - 我們將沒有通知關於此。當我們撥打IRunningObjectTable::Revoke
時,最後IExternalConnection::ReleaseConnection
也只會被調用一次。
從另一方面,如果我們不使用ROTFLAGS_REGISTRATIONKEEPSALIVE
標誌 - IExternalConnection
方法將上Register
和Revoke
不叫。但它會在和IRunningObjectTable::GetObject
最終Release
稱爲(的對象代理)多時間。如果我們自己沒有執行IExternalConnection
或者當外部參考文獻達到0時致電CoDisconnectObject
並且fLastReleaseCloses
- 我們將從ROT中刪除。但我們免費不叫CoDisconnectObject
(在這種情況下,行爲會像我們使用ROTFLAGS_REGISTRATIONKEEPSALIVE
),或者說把它叫做一定條件下。
優勢 - 我們可以跟蹤每一個我們的對象使用的情況下,沒有ROTFLAGS_REGISTRATIONKEEPSALIVE
標誌,並通過自我決定的,當外部裁判達到0或不需要斷開。
最後 - 如果我們調用IRunningObjectTable::GetObject
從同一公寓,我們稱之爲IRunningObjectTable::Register
- 我們有沒有代理服務器,而是直接對象指針。在這種情況下當然不會調用IExternalConnection
方法
現在它是有道理的。我已經使用戶外客戶端測試了場景,當它斷開連接時,對象被一直釋放到零。 –
@SevaAlekseyev - 是的,離開公寓客戶(真正的代理)和公寓內客戶之間的根本不同。然而,爲了最好的理解情況 - 很好的實現'自我對象上的IExternalConnection'(只有2個簡單的方法),在這之後會很清楚 – RbMm
從[IRunningObjectTable :: Register](https://msdn.microsoft.com/en-us/library/windows/desktop/ms680747.aspx):*「對於一個弱註冊(ROTFLAGS_REGISTRATIONKEEPSALIVE未設置)時,ROT將釋放每當最後強有力的參考對象被釋放。對於強註冊(ROTFLAGS_REGISTRATIONKEEPSALIVE集)的對象時,ROT防止物體被破壞,直至對象登記明確撤銷。「* – IInspectable
我讀過。你能解釋一下,「最後一個強烈的對象被釋放」是什麼意思?如果你剛剛從ROT獲得它,然後釋放它,它不會釋放該對象。在疲軟的情況下,ROT就像在強大的情況下持有一個參考。 –
我理解它的方式(我不得不承認我從未做過額外的檢查)是,強大的註冊請求'ROTFLAGS_REGISTRATIONKEEPSALIVE'確保ROT持有有效的引用,無論如何。如果沒有這個標誌,它會以類似的方式開始(沒有別的辦法,尤其是那些文檔說最初的'AddRef'總是會發生的),但是API保留在任何時候釋放條目的權利,尤其是。特定事件,如發佈代理。 –