0

我们开发了一个 STA ATL COM OOP 服务器,几乎一切正常。我们面临一个问题:当 COM 客户端通过 Windows 消息在内部获取任何 COM 调用的结果时,可以在等待 COM 调用的应答时处理 WM_PAINT 消息(或我猜的任何其他消息)。这本身可能是一个问题,但最大的问题是,在之前的 COM 调用完成之前,对服务器的所有调用都会失败(HRESULT=0x80010005),这是一个相当大的问题,因为它在我们的应用程序中经常发生。我们无法从绘图中删除 COM 调用。

我已经对此进行了大量研究,但找不到任何关于它的内容(除了这篇2006 年的文章说明了这个问题以及一些无法在我们的案例中应用的解决方案),但我看到的不仅是 WM_PAINT危险的是,我们在任何 Windows 事件(消息)中执行的对服务器的任何调用都可能导致相同的问题。

所以基本上我们可以有不同的解决方案,但不知道要使用哪些 COM 方法或如何使用: 1- 一个等待直到最后一个 COM 调用被处理并返回值的方法 2- 一个知道在服务器和处理 COM 答案的方法(全部从客户端调用) 3- 知道我们是否可以在客户端中实现 IMessageFilter 类以及如何处理它和处理调用等。

谢谢!

4

2 回答 2

0

由于 COM 客户端通过 Windows 消息在内部获取任何 COM 调用的结果,因此可以在等待 COM 调用的应答时处理 WM_PAINT 消息(或我猜的任何其他消息)。

没有任何东西可以将 COM 调用与WM_PAINT处理联系起来。这两个任务同时存在,但是当您选择 STA 作为模型时,这两个任务都在同一个线程上运行并且可能会相互阻塞。

对于绘画本身,​​您几乎无能为力,因为您最终将拥有一个消息处理程序来进行绘画。但是,您可以更改 COM 服务器和绘图处理程序以不干扰 COM。

您不需要直接从WM_PAINT. 构建您的服务器,使其异步发布所有 UI 更新,并且绘制处理程序只使用可用的最新数据。

您还可以将服务器移动到另一个单元、STA 或 MTA,这样它就不会与 UI 共享线程并并行运行。

于 2013-09-18T14:38:53.863 回答
0

我们已经解决了在客户端项目 (C++) 中实现 IMessageFilter 类的问题:

消息过滤器.h:

#include <atlbase.h>
#include <atlcom.h>

namespace SDKCOMSrvInterface
{
 class MessageFilter : public CComObjectRootEx<CComSingleThreadModel>, public IMessageFilter
 {
  BEGIN_COM_MAP(MessageFilter)
   COM_INTERFACE_ENTRY(IMessageFilter)
  END_COM_MAP()

  // Implement IMessageFilter methods here
  STDMETHODIMP_(DWORD) HandleInComingCall(
  DWORD dwCallType,
  HTASK threadIDCaller,
  DWORD dwTickCount,
  LPINTERFACEINFO lpInterfaceInfo)
  {
   return E_NOTIMPL;
  }

  STDMETHODIMP_(DWORD) RetryRejectedCall(
   HTASK threadIDCallee,
   DWORD dwTimeOut,
   DWORD dwRejectType)
  {
   return SERVERCALL_RETRYLATER;
  }

  STDMETHODIMP_(DWORD) MessagePending(
   HTASK threadIDCallee,
   DWORD dwTickCount,
   DWORD dwPendingType)
  {
   return PENDINGMSG_WAITDEFPROCESS;
  }
 };
}

并在 CoInitialize(NULL) 之后注册它:

CComObject<MessageFilter>* l_MessageFilter = NULL;
CComObject<MessageFilter>::CreateInstance(&l_MessageFilter);
CComPtr<IMessageFilter> l_OldMessageFilter;
hr = CoRegisterMessageFilter(l_MessageFilter, &l_OldMessageFilter);

这将确保如果我们尝试从客户端调用服务器并且服务器正忙,则将重试 COM 调用,直到服务器处理之前的调用,这正是解决并发问题所需要的。

于 2013-09-19T09:23:16.033 回答