在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,如果没有,它将运行恢复
我该怎么做?
答案 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生成的包装类使用相同的方法。