I'm looking for some feedback on an issue that I can workaround, but want to understand better. I have some multithreaded code where a worker thread uses the Win32 API PostMessage function to post a message to the main UI thread in order to update a TreeView. Some of the posted messages sometimes fail to ever appear via the UI thread's message pump, despite my logging showing that the PostMessage returned successfully.
I've already found numerous explanations of how this could happen if I'd done something funky in my message pump, due to the presence of a modal message pump in certain circumstances, but I'm not doing anything funky.
I think (but would like confirmed) that my problem is due to calling PostMessage too early in the UI thread's lifetime. My WinMain calls CreateWindowEx to create its main window, and the WM_CREATE handler for that window indirectly launches the background threads that will, fairly quickly, call PostMessage using the main windows's HWND, possibly even before the WM_CREATE handler finishes, very likely before WinMain's message pump is started.
Is it possible/likely that some messages in this situation would be lost, even though PostMessage returned success? In testing, I've determined that adding a small delay (Sleep(50)) in the worker thread before it calls PostMessage is enough to prevent any message loss. However, I'm not convinced that this is solving the underlying problem so would like to know if I need to keep digging.
EDIT:
There's only one message loop in all my code and it's not doing anything unusual beyond calling the usual TranslateAccelerator etc:
// Enter the message loop
while (GetMessage (&msg, NULL, 0, 0)) {
if (!TranslateMDISysAccel(hwndClient, &msg) && !TranslateAccelerator (hwndFrame, hAccel, &msg)) {
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
I've already found numerous explanations of how this could happen if I'd done something funky in my message pump, due to the presence of a modal message pump in certain circumstances, but I'm not doing anything funky.
Modal loops don't throw away window messages, unless they are coded wrong and don't pass unknown messages to TranslateMessage()/DispatchMessage() like they should.
I think (but would like confirmed) that my problem is due to calling PostMessage too early in the UI thread's lifetime.
If that were the case, PostMessage() would simply fail, but you have already ruled that out. As soon as a thread calls any user32.dll function, the message queue is created and can begin receiving messages, even if the queue is not polled right away.
Is it possible/likely that some messages in this situation would be lost, even though PostMessage returned success?
No. Something else is going on. Either your message loop is filtering messages incorrectly, or a malformed modal loop is discarding messages, or you are simply posting to the wrong HWND. Hard to say as you did not show any of your code.
In testing, I've determined that adding a small delay (Sleep(50)) in the worker thread before it calls PostMessage is enough to prevent any message loss.
What is your main thread normally doing during those 50ms? Sounds like something in your UI code is receiving and discarding your posted messages during that time.
On the other hand, how do the threads know which HWND to post to? Is your WM_CREATE handler passing its hwnd parameter to the threads, or are the threads relying on the HWND returned by CreateWindowEx()? In the latter case, PostMessage() should fail if called before CreateWindowEx() exits. Unless your receiving HWND variable is initially uninitialized and contains a random non-null value that PostMessage() interprets as a valid HWND elsewhere on the system.
Related
I need to pump COM messages while waiting for an event to fix a deadlock. It's better to pump as few messages as possible just to process that COM call. The best candidate for this role is CoWaitForMultipleHandles but starting from Vista it pumps WM_PAINT in addition to COM messages. 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.
I'm trying to pump COM messages sent to the hidden message-only window manually.
I have found two ways to get HWND of the hidden window:
((SOleTlsData *) NtCurrentTeb()->ReservedForOle)->hwndSTA using ntinfo.h from .NET Core. This seems to be undocumented and not reliable solution in terms of future changes.
Find window of OleMainThreadWndClass as suggested in this question. The problem is that CoInitialize does not create the window. 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.
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.
Is there a better way to pump COM messages without pumping WM_PAINT?
Update: you can force the window creation by calling CoMarshalInterThreadInterfaceInStream for any interface. Then call CoReleaseMarshalData to release the stream pointer. This is what I end up doing along with the search for OleMainThreadWndClass.
WM_PAINT is generated when there is no other message in the message queue and you execute GetMessage or use PeekMessage.
But WM_PAINT is only sent if you Dispatch it. Also there is no new WM_PAINT message until a window is invalidated again.
So it depends on you if you dispatch a WM_PAINT message or not. But be aware, there are other chances of reentrances like a WM_TIMER message.
The details about this are in the docs for 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. You know when you are reentered. It is always after a WM_PAINT... or similar messages that arrive like other input messages. 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. 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.
I noticed that some messages in WinAPI can be retrieved only in the "main message loop" with PeekMessage() (like WM_QUIT), others can only be retrieved in the user defined winProc() function (like WM_CLOSE and WM_SIZE), and some messages like WM_MOUSEMOVE are retrieved with both.
What's the difference? How do I know where the WM message is going to be sent to?
Messages that were posted with a NULL window handle can only be retrieved in the message loop. Necessarily so, DispatchMessage() can't do its job. This is quite rare.
But yes, WM_QUIT, note how PostQuitMessage() does not take a window handle. That's rather inevitable, when you call PostQuitMessage() you (usually) don't have any window left so only a NULL window handle is sensible. Of course its real intention is to make GetMessage() return FALSE and thus terminate the message loop.
The only other case I can think of are messages generated with PostThreadMessage(). Note how this is a pretty dangerous function, it should never be used to post messages to a thread that ever displays any window. Such messages fall in the bit-bucket when another message loop pumps. Like the one that allows the user to move/resize a window. Or the one that keeps MessageBox() modal. It is only useful in process and thread interop marshaling.
So just ignore this, it is a corner-case.
The usual WinAPI message loop looks something like this:
MSG msg;
while (GetMessage(&msg, hwnd, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Is it allowed not to call DispatchMessage() but to handle the message on your own? If not, how could I nicely approach this behavior while avoiding global variables and thread problems?
Edit:
I basically want to use my own callback function, which hasn't the WndProc signature. But I can't think of a way to call that function out of a WndProc without using static or global variables.
[Which would require locking, which I think isn't the best thing you can do with a callback function which probably gets called very frequently.]
Thanks for your help.
Is it allowed not to call DispatchMessage() but to handle the message on your own? If not, how could I nicely approach this behavior while avoiding global variables and thread problems?
If you are planning to use multiple threads in your GUI then each thread that creates a window will need to manage it's own message queue.
From this page: http://msdn.microsoft.com/en-us/library/ms810439.aspx
Changes to the Message Loop
Applications with multiple threads must include a message loop in each
thread that creates a window. The message loop and window procedure
for a window must be processed by the thread that created the window.
If the message loop does not reside in the same thread that created
the window, the DispatchMessage function will not get messages for the
window. As a result, the window will appear but won't show activation
and won't repaint, be moved, receive mouse messages, or generally work
as you expect it to.
You can react to a message there, but you still need/want to call DispatchMessage and actually handle the message in your normal wndproc. I'd be happy to say more about avoiding globals and/or threading problems, but it's hard to comment without more details about what you want to avoid.
Yes, you can handle the message yourself, if you wish. I usually set the result field to 0, but Windows only make use of this field for a few messages.
I have an external application that calls my application and is supposed to end it when the job is done. The log from this external application claims it uses WM_CLOSE on my app.
How can I intercept the WM_CLOSE message in my application to do some cleanup operations? I tried at_exit() and wrapping it in a class, but I think I have the wrong approach.
The official solution for console applications is HandlerRoutine, a callback set by SetConsoleCtrlHandler. Windows will call your handler with a CTRL_CLOSE_EVENT argument in case of a WM_CLOSE exit.
When you're using a class method with SetConsoleCtrlHandler, it must be a static method - Windows won't provide you with a this pointer.
You could just handle WM_CLOSE in your message loop to do whatever cleanup is necessary, or even abort the close (by returning 1 instead of 0). See e.g. this: http://cboard.cprogramming.com/windows-programming/141438-handling-wm_close-wm_destroy.html#post1056273
Edit: for console applications, this may be of interest: http://support.microsoft.com/kb/178893
You must create hidden window using winapi, and handle WM_CLOSE message in its message loop. Is your app using any gui elements?
The easiest way I think is to call PeekMessage from time to time.
BOOL IsCloseEventReceived()
{
MSG msg;
return PeekMessage(&msg, NULL, WM_CLOSE, WM_CLOSE, PM_NOREMOVE);
}
This function should work to check if a WM_CLOSE message has been posted. It's not blocking, and you'll need to call it on a regular basis.
I might be wrong, but I think you don't need a hidden window to handle messages, a message queue is attached to your process the first time you call a messages-related function, like PeekMessage. However if you receive a WM_CLOSE message prior to your first call of this function it might be lost.
Is there a way to hook for a particular windows message without subclassing the window.
There is WH_GETMESSAGE but that seems create performance issues.
Any other solutions apart from these which doesn't deteriorate performance?
AFAIK there's no better solution than what you mentioned. And, of course, subclassing the window is better than hooking all the messages of the thread.
Let's think which path the message passes up until it's handled by the window:
The message is either posted or sent to the window, either by explicit call to PostMessage/SendMessage or implicitly by the OS.
Posted messages only: eventually the thread pops this message from the message queue (by calling GetMessage or similar), and then calls DispatchMessage.
The OS invokes the window's procedure by calling CallWindowProc (or similar).
The CallWindowProc identifies the window procedore associated with the window (via GetClassLong/GetWindowLong)
The above procedure is called.
Subclassing - means replacing the window procedure for the target window. This seems to be the best variant.
Installing hook with WH_GETMESSAGE flag will monitor all the messages posted to the message queue. This is bad because of the following:
Performance reasons.
You'll get notified only for windows created in the specific thread
You'll get notified only for posted messages (sent messages will not be seen)
A "posted" message doesn't necessarily means "delivered". That is, it may be filtered by the message loop (thrown away without calling DispatchMessage).
You can't see what the actual window does and returns for that message.
So that subclassing seems much better.
One more solution - in case your specific message is posted (rather than sent) you may override the message loop, and for every retrieved message you may do some pre/post-processing