简体   繁体   English

如何在不泵送WM_PAINT的情况下在STA中泵送COM消息?

[英]How pump COM messages in STA without pumping WM_PAINT?

I need to pump COM messages while waiting for an event to fix a deadlock. 我需要在等待事件修复死锁时泵送COM消息。 It's better to pump as few messages as possible just to process that COM call. 最好仅泵送尽可能少的消息以处理该COM调用。 The best candidate for this role is CoWaitForMultipleHandles but starting from Vista it pumps WM_PAINT in addition to COM messages. 此角色的最佳人选是CoWaitForMultipleHandles,但从Vista开始 ,除了COM消息外,它还会泵送WM_PAINT。 Pumping WM_PAINT is too dangerous for me from re-entrance perspective and I don't want to install a custom shim database as a solution for this problem. 从重新进入的角度来看,泵送WM_PAINT对我来说太危险了,我不想安装自定义填充程序数据库来解决此问题。

I'm trying to pump COM messages sent to the hidden message-only window manually. 我正在尝试手动发送发送到隐藏的仅消息窗口的COM消息。

I have found two ways to get HWND of the hidden window: 我发现了两种获取隐藏窗口的HWND的方法:

  1. ((SOleTlsData *) NtCurrentTeb()->ReservedForOle)->hwndSTA using ntinfo.h from .NET Core. ((SOleTlsData *) NtCurrentTeb()->ReservedForOle)->hwndSTA使用.NET Core中的ntinfo.h This seems to be undocumented and not reliable solution in terms of future changes. 就将来的更改而言,这似乎是未记录的且不是可靠的解决方案。
  2. Find window of OleMainThreadWndClass as suggested in this question . 查找此问题建议的OleMainThreadWndClass窗口。 The problem is that CoInitialize does not create the window. 问题是CoInitialize不会创建窗口。 It is created later on first cross-apartment call which may or may not happen in my application. 它是在以后的第一个跨部门调用中创建的,在我的应用程序中可能会或可能不会发生。 Running the search loop every time I need HWND is bad from performance perspective but caching HWND seems impossible because I don't know when it's created. 从性能的角度来看,每次需要HWND时都运行搜索循环是很糟糕的,但是缓存HWND似乎是不可能的,因为我不知道它是何时创建的。

Is there a way to determine if the hidden window is created for the current apartment? 有没有办法确定是否为当前公寓创建了隐藏窗口? I suppose it will be cheaper than the loop and then I could find and cache HWND. 我想它将比循环便宜,然后我可以找到并缓存HWND。

Is there a better way to pump COM messages without pumping WM_PAINT? 有没有更好的方法来泵送COM消息而无需泵送WM_PAINT?

Update: you can force the window creation by calling CoMarshalInterThreadInterfaceInStream for any interface. 更新:您可以通过为任何接口调用CoMarshalInterThreadInterfaceInStream来强制创建窗口。 Then call CoReleaseMarshalData to release the stream pointer. 然后调用CoReleaseMarshalData释放流指针。 This is what I end up doing along with the search for OleMainThreadWndClass . 这就是我最终对OleMainThreadWndClass的搜索。

WM_PAINT is generated when there is no other message in the message queue and you execute GetMessage or use PeekMessage. 当消息队列中没有其他消息并且您执行GetMessage或使用PeekMessage时,将生成WM_PAINT

But WM_PAINT is only sent if you Dispatch it. 但是WM_PAINT仅在您调度它时发送。 Also there is no new WM_PAINT message until a window is invalidated again. 在再次使窗口无效之前,也没有新的WM_PAINT消息。

So it depends on you if you dispatch a WM_PAINT message or not. 因此,这取决于您是否调度WM_PAINT消息。 But be aware, there are other chances of reentrances like a WM_TIMER message. 但是请注意,还有其他重入的机会,例如WM_TIMER消息。

The details about this are in the docs for WM_PAINT . 有关详细信息,请参阅WM_PAINT的文档。

From my point of view the best solution would be to set you application in a "wait" mode, that even can handle WM_PAINT in this undefined waiting state. 从我的角度来看,最好的解决方案是将应用程序设置为“等待”模式,甚至可以在此未定义的等待状态下处理WM_PAINT。 You know when you are reentered. 您知道何时重新进入。 It is always after a WM_PAINT... or similar messages that arrive like other input messages. 它总是在WM_PAINT ...或类似其他输入消息之后到达的消息之后。 So I don't see any problems here. 因此,我在这里看不到任何问题。 An STA has one thread and you always process messages to an end, until you execute GetMessage , launch a modal dialog or show a MessageBox. STA有一个线程,您始终将消息处理到最后,直到执行GetMessage ,启动模式对话框或显示MessageBox。 When you are inside some message handling, nothing will disturb you. 当您在进行某些邮件处理时,没有任何事情会打扰您。

Maybe an other solution would be to wait inside a second thread for this event. 也许另一个解决方案是在第二个线程内等待此事件。 This thread may not have any windows and you can translate the event to anything you need in your application. 该线程可能没有任何窗口,您可以将事件转换为应用程序中所需的任何内容。

So you question may not have enough information how this deadlock really appears. 因此,您可能没有足够的信息怀疑这种僵局是如何真正出现的。 So this answer may not be sufficient. 因此,这个答案可能还不够。

After writing als this I tend to the opinion that this is an XY problem. 在写完als之后,我倾向于认为这是一个XY问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM