我需要在等待事件修复死锁时抽取COM消息。为了处理COM调用,尽可能少地输出消息会更好。这个角色的最佳候选者是CoWaitForMultipleHandles,但starting from Vista除了COM消息之外它还支持WM_PAINT。从重新入口的角度来看,抽取WM_PAINT对我来说太危险了,我不想安装自定义填充程序数据库作为解决此问题的方法。
我尝试将手动发送到隐藏的仅消息窗口的COM消息泵出来。
我找到了两种方法来获取隐藏窗口的HWND:
((SOleTlsData *) NtCurrentTeb()->ReservedForOle)->hwndSTA
使用.NET Core中的ntinfo.h。对于未来的变化而言,这似乎没有记录,也不是可靠的解决方案。OleMainThreadWndClass
的窗口。问题是CoInitialize
没有创建窗口。它是在第一次跨公寓电话后创建的,可能会也可能不会在我的应用程序中发生。每次我需要HWND时运行搜索循环从性能角度来看都很糟糕,但缓存HWND似乎是不可能的,因为我不知道它何时被创建。有没有办法确定是否为当前公寓创建了隐藏窗口?我想它会比循环便宜,然后我可以找到并缓存HWND。
有没有更好的方法在不泵送WM_PAINT的情况下泵送COM消息?
更新:您可以通过为任何界面调用CoMarshalInterThreadInterfaceInStream
来强制创建窗口。然后调用CoReleaseMarshalData
以释放流指针。这就是我最终在搜索OleMainThreadWndClass
时所做的事情。
答案 0 :(得分:-3)
WM_PAINT
。
但WM_PAINT
仅在您发送时发送。此外,在窗口再次失效之前,没有新的WM_PAINT
消息。
因此,如果您发送WM_PAINT
消息,则取决于您。但要注意,还有其他机会可以像WM_TIMER
消息那样重入。
有关此内容的详细信息,请参阅WM_PAINT的文档。
从我的角度来看,最好的解决方案是将应用程序设置为等待"等等。模式,甚至可以在这个未定义的等待状态下处理WM_PAINT。你知道什么时候你被重新进入。它总是在WM_PAINT ...或类似的消息之后到达,就像其他输入消息一样。所以我在这里看不到任何问题。 STA有一个线程,您始终处理消息到结尾,直到您执行GetMessage
,启动模式对话框或显示MessageBox。当你在一些消息处理中时,什么都不会打扰你。
也许其他解决方案是在第二个线程内等待此事件。此主题可能没有任何窗口,您可以将事件转换为应用程序中需要的任何内容。
所以你的问题可能没有足够的信息,这个死锁是如何真正出现的。所以这个答案可能还不够。
在写完这篇文章后,我倾向于认为这是一个XY问题。