2012-05-21 24 views
2

我正在編寫COM服務器,並且我寫了代碼來檢測COM客戶端意外關閉時的情況,在這種情況下,我應該關閉COM服務器內部的COM服務器代碼。如何從COM服務器調用釋放

我怎樣才能做到這一點?

UPD:我有COM服務器被絞死或更正確的情況我無法從COM客戶端連接到COM服務器,但包含COM服務器的應用程序是活動的,所以我認爲COM服務器可以檢測到所有舊的COM客戶端已斷開連接/關閉/崩潰,並且應用程序將重新啓動,因爲沒有連接新客戶端。

我已經寫在COM客戶端下面的代碼在單獨的線程

while(not we are closing) 
{ 
    unknown->QueryInterface(IComServer, &server); 

    if (server) 
    return; 
} 

使COM客戶端可以等到服務器將真正準備工作

UPD2:剛剛測試:13分鐘我的COM後服務器已關閉

+0

您認爲這樣做的好處是什麼? –

+0

@David Heffernan:顯然他不希望COM服務器進程在無限期內停頓。 – sharptooth

回答

4

COM定期ping客戶端,看看他們是否仍然活着,並運行死亡客戶端的接口。所以你的服務器最終會發現。

+1

從來沒有聽說過這個,也沒有看到它自己。兩小時前我啓動了一個進程外服務器,並殺死了客戶端。它仍在運行。愛看這方面的參考,它不穀歌。 –

+2

客戶端斷開連接6分鐘或12分鐘後應該發生斷開,fwiw。它確實發生。您是否在服務器對象的Release()方法上放置了一個斷點以確認它未被調用?可能有另一個引用保持你的服務器活着。 –

+0

@Larry,通過獲取對msword的_Application接口的單引用,我保持簡單。它沒有發生。 –

3

這是一個存在漏洞,無論何時存在兩個進程或進程互相處於互相操作狀態。其中一人死亡,另一人死亡,不知道死亡過程中再也沒有其他請求。在進程外COM服務器的情況下,沒有人打算調用IUnknown :: Release()來銷燬對象。 COM對於這個問題沒有其他的內置修復。進程內服務器沒有這個問題,崩潰的進程也將服務器也取出。這也是一個問題,沒有很好的清理,但更容易處理。

讓服務器從此恢復是必須添加自己的東西。例如,您可以讓客戶端傳遞其進程ID,以便服務器可以獲取進程句柄,並通過WaitForMultipleHandles()檢測客戶端何時崩潰。假設他們都住在機器上,那當然不是COM要求,也不是服務器可以找到的東西。

+0

我喜歡你的想法,以這種方式 - Com客戶端接收Com服務器的句柄,用WaitForMultipleHandles創建線程,當Com服務器失敗時,它使空指針到服務器。所以客戶端可能永遠不會掛起服務器 –

0

COM將在客戶端死機後的一段時間內釋放服務器端對象在一個out-proc服務器中,但只有當該對象中沒有執行調用時纔會釋放該服務器端對象。這是關鍵 - COM不可能阻止正在進行的呼叫。因此,解決方案是讓方法運行時間短,並保證在幾秒鐘的合理時間內完成。這樣,一旦客戶端死亡,沒有新的呼叫到達,一段時間後,進行中的呼叫自然結束,然後超時後COM釋放服務器中的對象,服務器可以自然停止。