2012-06-06 46 views
2

在C++中,MFC:檢查存在的COM指針

我有一個CComPointer:

CComPointer<IMyTask> m_pTask; 

有很多的在我的代碼的地方,我把這個ComPointer運行任務的方法。例如:

void method1() 
{ 
    if (FAILED(hRet = m_pTask->MyFunc1())) 
        ..... 
} 

void method2() 
{ 
    if (FAILED(hRet = m_pTask->MyFunc2())) 
        ..... 
} 

我嘗試解決MyTask關閉時要恢復的問題。 我寫了一個方法recover(),它將CoCreate重新運行到MyTask,它實際上解決了這個問題。

我可以看到,如果MyTask死了,我得到一個人力資源失敗代碼-2147023174,RPC服務器不可用。但是,com指針m_pTask有完整的數據(它不知道任務已經死了)。

我可以做這樣的事情:

void method1() 
{ 
    if (FAILED(hRet = m_pTask->MyFunc1())) 
     if (hRet == -2147023174) 
      recover(); 
        ..... 
} 

void method2() 
{ 
    if (FAILED(hRet = m_pTask->MyFunc2())) 
     if (hRet == -2147023174) 
      recover(); 
        ..... 
} 

但是,因爲我有很多打電話來通過compointer方法,我想讓更多的東西一般。 我希望每次嘗試通過ComPointer運行一個方法時,在方法運行之前檢查該任務是否已經存在,如果沒有,則運行recover方法。 因爲即使任務已經結束,ComPointer仍然擁有CoCreate時間的所有數據,我不知道該怎麼做。

我該怎麼辦?

由於系統中出現某些錯誤導致該任務死機,而現在我的解決方案不需要找出任務失敗的原因,只是爲了恢復它。我正在尋找一個通用的解決方案 - 比如ComPointer的包裝,但是我希望包裝類只檢查MyTask是否仍然存在,如果它是 - 它將返回ComPointer,如果不是,它將運行恢復。

我該怎麼辦?

+0

這不是MFC它是ATL。 –

+0

壞主意,恕我直言。網絡往返不便宜;你的數量實際上翻了一番。無論如何,DCOM運行時檢查死了的服務器 - 有一個週期性的ping。 –

+0

@Seva Alekseyev:沒有,他沒有增加他們的金額,如果服務器沒問題,他不需要恢復,這通常是這種情況。如果服務器不好,然後重新啓動它需要很多時間。 – sharptooth

回答

0

好的,這是一般性問題的一般答案。我不想知道,爲什麼這個任務實際上是死的,當指針沒有時。爲任務指針編寫一個包裝,然後使用它。它會是這個樣子:

class CMyTaskWrapper 
{ 
    CComPtr<IMyTask> m_ptr; 
    ... 
    HRESULT myFunc1() 
    { 
     HRESULT hRes = m_ptr->myFunc1(); 
     if(hRes == 0x800706BA) 
     { 
      recover(); 
     } 
     return hRes; 
    } 
    ... //here you should list all members of IMyTask 
}; 

EDIT1:加入了宏樣本(見註釋#2)

MYMACRO_0(HRESULT_GETTER, POINTER, FUNCTION) \ 
HRESULT_GETTER = POINTER->FUNCTION(); \ 
if(HRESULT_GETTER == 0x800706BA) recover(); \ 
HRESULT_GETTER = POINTER->FUNCTION() 

MYMACRO_1(HRESULT_GETTER, POINTER, FUNCTION, PARAM1) \ 
HRESULT_GETTER = POINTER->FUNCTION(PARAM1); \ 
if(HRESULT_GETTER == 0x800706BA) recover(); \ 
HRESULT_GETTER = POINTER->FUNCTION(PARAM1) 

//here you should add MYMACRO_2 ... MYMACRO_N 

您可以在下面的方式來使用它:

MYMACRO_0(hRes, m_pTask, MyFunc1); 
MYMACRO_1(hRes, m_pTask, MyFunc2, parameter_to_pass); 

這可能會有所幫助,並且這會隱藏函數列表,但使用此類代碼不是一個好主意。

+0

感謝您的回答。 由於在系統中出現錯誤而導致任務失效,現在我的解決方案不需要找到任務失敗的原因,只需恢復它即可。 在您的解決方案中,擁有ComPointer的項目必須知道IMyTask的所有方法,並且如果IMyTask發生更改,則也必須更改CMyTaskWrapper。 我正在尋找更通用的解決方案 - 你說的包裝是一個好主意,但我希望包裝類將只檢查MyTask是否仍然存在,如果它是 - 它將返回ComPointer,如果不是,它會運行recover.ideas? – user1439691

+0

除非使用一些特殊的代碼生成器,例如Visual C++用'#import'關鍵字進行操作,否則沒有更多的通用方法。我的答案可以是隻對特定的案例子集。例如,您可以編寫一組宏(詳細信息請參閱帖子編輯,註釋不適用於代碼)。 – Forgottn

+0

關於你的最後一句話。如果可以的話,你可以嘗試添加一個虛擬方法,它可以從包裝器中安全地調用,並檢查服務是否正常。但我不確定這是否會是更好的方法。 – Forgottn

0

CComPointer的實現相當簡單。您可以輕鬆剪切並粘貼它,以形成您自己的智能指針類的基礎。

CComPointer的實現依賴於覆蓋「 - >」運算符。這避免了需要知道接口提供什麼方法​​的任何事情。每個電話都被有效攔截並轉發。

在您可以構建的新智能指針類中,需要額外的功能來實現「 - >」操作覆蓋。

驗證呼叫的檢查更困難。

我認爲QueryInterface是一個有效的調用,您可以用它來檢查連接是否存在 - QueryInterface保證存在,並且需要調用實際的實現。

但是總是會有競爭條件 - 連接可能會在您的檢查呼叫和您的真實呼叫之間失敗。

因此,你可能會更好,只是要做出真正的呼叫,如果它失敗了嘗試恢復和再次調用 - 這很難做到一個很好的模式 - 可能是最容易實現的宏觀看Forgottn的答案。

+0

這將仍然需要在返回指針之前進行檢查。如果通過調用一些特殊功能無法進行檢查,該功能會檢查與RPC服務器的連接是否存在,您的想法將無法工作。 – Forgottn

+0

請參閱上面的更新 – morechilli

+0

不幸的是,' - >'運算符實際上並沒有進行該調用,它只是返回一個指向該調用的指針。 C++的怪癖之一。 –

0

這聽起來像你想要一個自定義的DCOM代理,而不是midl和Windows提供的默認邏輯。這是可能的,但它也是很多工作。如果您需要向使用COM創建對象的第三方代碼提供的自定義行爲,這是最佳選擇。

當您控制客戶端代碼時,只需編寫一個實現相同COM接口的包裝類就可以更簡單,並通過將每個調用轉發給遠程服務器來實現。

0

MFC類嚮導允許您圍繞com組件生成包裝類。 This page describes how.

一旦包裝類已經生成 - 你可以編輯任何方法來實現你的重試邏輯。您可以對#import directive生成的包裝類使用相同的方法。