CoWaitForMultipleHandles API doesn't behave as documented

前端 未结 1 420
刺人心
刺人心 2020-12-29 13:24

This was triggered by another question I was looking at. It might be too long to read, so please bear with me.

Apparently, CoWaitForMultipleHandles does

相关标签:
1条回答
  • 2020-12-29 13:43

    CoWaitForMultipleHandles is intended to process COM window messages (e.g. cross-apartment marshalling) and a few others (don't ask me which) in STA, or simply block in MTA. In this blog post, «Managed blocking» by Chris Brumme, it says CWFMH processes "just the right amount" of window messages. However, since it leaves any non-COM posted window message in the queue, the queue may still fill up, just not with COM window messages.

    According to this document, «Migrating your Windows 8 Consumer Preview app to Windows 8 Release Preview», it says:

    CoWaitForMultipleHandles function is no longer supported in Windows Store apps. In addition the following CoWait_Flags have been removed:

    COWAIT_DISPATCH_CALLS

    COWAIT_DISPATCH_WINDOW_MESSAGES

    If you really want to process all messages, you should use MsgWaitForMultipleObjectsEx in a message loop with GetMessage or PeekMessage with PM_REMOVE. Doing so means a potential reentrancy frenzy. You still don't control further calls into the STA from other components down the stack. That is, a modal dialog (e.g. Common Dialog Box for Open) might pump every message in a plain-old window message loop, but some framework might call CoWaitForMultipleHandles.

    Bottom line is, if you're doing intensive processing or blocking operations, delegate it to another thread (possibly using a queue), and if needed tell the invoking UI thread to update after the operation is done.

    This is different than e.g. lengthy UI calls, such as OLE embedding or a modal dialog, where there's usually a window message loop somewhere along the stack. Or from lengthy but chunkable/resumable operations (e.g. a state machine), where you can cooperate by processing messages once in a while, or by using wait functions that return when there are messages so you can process them before waiting again.

    Be careful, this only works well for one handle; for multiple handles e.g. mutexes, you'd want either all or none, and the next best approach is an active loop, with a timed-out call to WaitForMultipleObjects followed by a PeekMessage with PM_REMOVE window message loop. This is a border-line case, acceptable for a UI application that is the user's center of attention (e.g. it's their main work), but unacceptable if such code may run unattended and on demand. Unless you know for sure that it needs to happen in an STA or UI thread, my advice is don't do this.

    Finally, you should probably open a bug at Microsoft Connect, at least to update the documentation. Or actually make it work as "expected".

    0 讨论(0)
提交回复
热议问题