在" PostMessage"中调用COM对象方式

时间:2015-06-17 15:26:57

标签: winapi com com+ dcom

我有一个STA线程,我正在执行某些操作。由于环境的限制(Office),有些事情我现在还做不到。但是,在当前的消息泵循环完成后,我可以立即执行这些操作。

我通常使用自己的仅消息窗口句柄来执行此操作,我将使用PostMessage向其发布消息。但是,考虑到环境和手头的体系结构,操作与来自其他线程/进程的其他COM对象调用一起排队是至关重要的。或者更准确地说,调用后操作需要在CoWaitForMultipleHandles调用期间执行。

COM(+)是否提供了一种调用方法的机制"稍后"?除了:

  • 自己创建一个线程(或以其他方式重用我自己创建的线程)。使它成为一个STA线程。 Marshal我对该线程的对象接口。使用ICallFactory为我的异步接口创建一个调用对象。从这个次要线程中解雇并忘记。
  • 严格为回发创建MTA对象(目标COM服务器仍然是原始STA线程上的STA对象)。实例化时,COM将为我创建一个线程。调用该MTA对象来安排回发(使用与以前相同的ICallFactory方法)。
  • 将COM调度程序窗口句柄和PostMessage挖出来。

前两个需要一个单独的线程,这似乎是不可取的。最后一个是黑客。

1 个答案:

答案 0 :(得分:0)

以下是一些可以尝试的黑客攻击。我自己没有尝试CoWaitForMultipleHandles,所以我不确定它们中的任何一个是否适用于托管的Office环境:

  • Office提供IMsoComponentManager服务。您实施IMsoComponent(查看this以获取一些示例代码)。希望IMsoComponent::FDoIdle可能有用。

  • SetTimer可以接受TIMERPROC lpTimerFunc。你不必为它创建一个窗口,你可以使用ATL thunk或类似的技术来创建一个C ++闭包。我已使用SetTimer完成此操作并且它可以正常工作,但我不确定它是否适用于CoWaitForMultipleHandles,因为计时器回调通常会在DispatchMessage内调用。此外,timer gets low priority in message dispatching,所以可能不按顺序。

  • WH_FOREGROUNDIDLE/ForegroundIdleProc可能很有趣,使用ATL thunk。当后者空闲时,也应该从CoWaitForMultipleHandles内部调用它。

  • 查看您的STA线程上的自定义COM message filter是否有用。 已更新,您澄清了它是一个Office线程,因此很可能它有自己的COM消息过滤器。也许,你可以在你的通话范围内覆盖它。

  • 查看对象上实现IAdviseSink是否有用。此接口是AFAIK COM规则的唯一异常,因为当通过另一个公寓的COM代理调用时,其方法称为异步。也许,这是解决问题的最佳选择。

  • 已更新,既然我们确定您已经在MSO STA线程上运行,那么还有另一个黑客攻击。您可以为调用范围启动嵌套模式消息循环。然后,您可以控制每个消息泵循环。这是我通常不推荐的DoEvents式黑客攻击,但您已经处于黑客攻击区。您至少需要禁用Office UI(针对调用范围)以限制重新入侵的机会。然后,您使用IMsoComponentManager::FPushMessageLoop msoloopDoEvents启动嵌套消息循环,并在每次新迭代(泵)时调用IMsoComponent::FContinueMessageLoop