科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件COM高手总结的八个经验和教训

COM高手总结的八个经验和教训

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

我为许多富于创造性的使用 COM 的工作方式感到惊讶。

作者:Jeff Prosise 来源:VC知识库 2007年10月19日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
使用线程或异步调用来避免 DCOM 超时设定太长

  总是有人问我当 DCOM 无法完成远程实例化请求或方法调用时出现的超时设定太长的问题。典型的场景如下:客户端调用 CoCreateInstanceEx 来实例化远程机器上的一个对象,但是这台机器临时离线了。在 Windows NT 4.0 上,激活请求不会立即失败,DCOM 可能会花上一分钟或更长时间来返回失败的 HRESULT。DCOM 还可能花费很长时间,使指向已不再存在或其主机已离线的远程对象的方法调用失败。如果可能,开发人员应该如何避免这些较长的超时设定呢?

  要回答这个问题,几句话是讲不清楚的。DCOM 高度依赖于基础网络协议和 RPC 子系统。并没有什么神奇的设置可让您限制 DCOM 超时设定的持续时间。但是,我经常使用两种技巧来避免较长超时设定的负作用。

  在 Windows 2000 中,当调用在 COM 信道中挂起时,您可以使用异步方法调用来释放调用线程。(有关异步方法调用的介绍,请参 MSDN Magazine 2000 年 4 月刊的“Windows 2000: Asynchronous Method Calls Eliminate the Wait for COM Clients and Servers Alike”。如果异步调用在合理时间内没有返回,您可以通过调用用于初始化调用的调用对象上的 ICancelMethodCalls::Cancel 来取消它。

   Windows NT 4.0 不支持异步方法调用,甚至在 Windows 2000 中也不支持异步激活请求。怎么解决呢?从背景线程调用远程对象(或是实例化该对象的请求)。使主线程在事件对象上阻塞,并指定超时设定值以反映您愿意等待的时间长度。当调用返回时,让背景线程来设置事件。假设主线程使用 WaitForSingleObject 阻塞,当 WaitForSingleObject 返回时,返回值可以告诉您,返回是因为方法调用或激活请求返回,还是因为您在 WaitForSingleObject 调用中指定的超时设定到期。您不能在 Windows NT 4.0 中取消挂起调用,但是至少主线程可以自由地执行自己的任务。

  下面的代码演示了基于 Windows NT 4.0 的客户端如何才能从背景线程调用对象。

//////////////////////////////////////////////////////
// Placing a Method Call from a Background Thread
///////////////////////////////////////////////////// 
HANDLE g_hEvent;
IStream* g_pStream;

// Thread A
g_hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
CoMarshalInterThreadInterfaceInStream (IID_IFoo, pFoo, &g_pStream);
DWORD dwThreadID;
CreateThread (NULL, 0, ThreadFunc, NULL, 0, &dwThreadID);
DWORD dw = WaitForSingleObject (g_hEvent, 5000);
if (dw == WAIT_TIMEOUT) {
 // Call timed out
}
else {
 // Call completed
}
...

// Thread B
IFoo* pFoo;
CoGetInterfaceAndReleaseStream (g_pStream, IID_IFoo, (void**) &pFoo);
pFoo->Bar (); // Make the call!
SetEvent (g_hEvent);
CloseHandle (g_hEvent);

  在此示例中,线程 A 封送了一个 IFoo 接口指针,并启动线程 B。线程 B 取消封送了该接口指针,并调用 IFoo::Bar。无论调用返回所花费的时间有多长,线程 A 都不会阻塞超过 5 秒钟,因为它在 WaitForSingleObject 的第二个参数中传递的是 5,000 (单位为微秒)。这并不是太好的办法,但是如果“无论在线路的另一端发生什么情况,线程 A 都不会挂起”这一点很重要的话,忍受这种麻烦也算值得。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章