检查COM指针的存在

时间:2012-06-06 12:03:02

标签: c++ com atl dcom

在c ++中,MFC:

我有一个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死了,我的HR失败代码为-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是否仍然存在,如果它是-it将返回ComPointer,如果没有,它将运行恢复

我该怎么做?

4 个答案:

答案 0 :(得分: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);

这可能会有所帮助,这会隐藏功能列表,但是使用这样的代码并不是一个好主意。

答案 1 :(得分:0)

CComPointer的实现相当简单。您可以轻松地剪切和粘贴它,以形成您自己的智能指针类的基础。

CComPointer实现依赖于覆盖“ - &gt;”运营商。这样就无需了解界面提供的方法。每次通话都被有效拦截然后转发。

在你的新智能指针类中,你可以构建你需要额外的功能来实现“ - &gt;”操作员覆盖。

验证通话的更多检查更难。

我认为QueryInterface是一个有效的调用,你可以用来检查连接是否存活 - 确保QueryInterface存在,并且需要调用真正的实现。

然而,总是存在竞争条件 - 在您的支票呼叫和您的真实呼叫之间连接可能会失败。

因此,你可能更好地进行真正的调用,如果它失败了,试着恢复并再次调用 - 这很难以一个很好的模式进行 - 可能最容易用宏来实现,看看Forgottn的答案。

答案 2 :(得分:0)

听起来你想要一个自定义的DCOM代理,而不是midl和Windows提供的默认逻辑。这是可能的,但这也是很多工作。如果您需要提供给使用COM创建对象的第三方代码的自定义行为,这是最佳选择。

当你控制客户端代码时,只编写一个实现相同COM接口的包装类可能更简单,并通过将每个调用转发到远程服务器来实现。

答案 3 :(得分:0)

MFC类向导允许您围绕com组件生成包装类。 This page describes how.

生成包装类后,您可以编辑任何方法以在其中实现重试逻辑。您可以对#import directive生成的包装类使用相同的方法。