MSDN文檔爲CCmdTarget的:: OnFinalRelease方法很簡單:在什麼條件下調用CCmdTarget :: OnFinalRelease?
框架調用的最後一個OLE引用或從 對象釋放時。
我創建了一個子類CCmdTarget的
的class CMyEventHandler : public CCmdTarget { ... }
我想在什麼條件下OnFinalRelease方法將被調用弄清楚。我有一些代碼,看起來是這樣的:
CMyEventHandler* myEventHandler = new CMyEventHandler();
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionAdvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
// Application continues...events arrive...eventually the event sink is shutdown
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
使用此代碼,我觀察到OnFinalRelease方法不會被調用。這意味着我有內存泄漏。因此,我修改了總結代碼,如下所示:
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
delete myEventHandler;
myEventHandler = NULL;
此部分代碼在整個一天中定期觸發。我現在注意到的是,雖然myEventHandler的封裝實例的析構函數按預期調用,但OnFinalRelease函數現在正在調用!更糟糕的是,它不是被包裝的實例所調用,而是被一個新創建的CMyEventHandler實例所調用!心想這可能是由於引用計數的問題,我修改了線並封裝代碼:
CMyEventHandler* myEventHandler = new CMyEventHandler();
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(TRUE);
AfxConnectionAdvise(myEventSource, DIID_IMyEventInterface, pUnk, TRUE, myCookie);
pUnk->Release();
// Application continues...events arrive...eventually the event sink is shutdown
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(TRUE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, TRUE, myCookie);
pUnk->Release();
delete myEventHandler;
myEventHandler = NULL;
我讓這跑了一整天,現在觀察到OnFinalRelease永遠不會被調用。被包裝的實例的析構函數按照我所期望的被調用,但是我仍然感到不安,因爲我顯然不瞭解OnFinalRelease被調用的情況。是OnFinalRelease呼籲一些延遲,或者有辦法迫使它開火?什麼會觸發OnFinalRelease被調用?
如果很重要,事件源是一個.NET程序集,通過COM interop公開事件。
我的印象是第一次AddRef發生在調用GetIDispatch時,而不是在構造上,所以沒有必要在myEventHandler上調用Release。這是不正確的? – JadeMason
施工後立即查看「CCmdTarget」的'm_dwRef'成員。我打賭它是1.(或者你可以檢查MFC的源代碼,MFC附帶源代碼。) –