I have a window on thread A, which at some point (as a result of a message being received on its wndproc) triggers an action on thread B, and then waits for the action to complete (using some sort of sync mechanism). Thread B then calls MoveWindow()
, to move a child window within thread A's window (a standard textbox, for example). At this point the program goes into a state of deadlock for some reason. If MoveWindow()
is being called from thread A, everything works. Any ideas why?
views:
213answers:
5You need to make sure that the message pump of the thread is running while you are waiting.
You may want to loop with PeekMessage() (or maybe GetMessage()) and DispatchMessage().
What is the "some sort of sync mechanism"? If it is WaitFor(Multiple)Object(s), you can use MsgWaitForMultipleObjects(Ex) instead to wake up when you have a message and dispatch it as Lucero suggests.
Thread affinity of user interface objects, part 1: Window handles:
Different objects have different thread affinity rules, but the underlying principles come from 16-bit Windows.
The most important user interface element is of course the window. Window objects have thread affinity. The thread that creates a window is the one with which the window has an inseparable relationship. Informally, one says that the thread "owns" the window. Messages are dispatched to a window procedure only on the thread that owns it, and generally speaking, modifications to a window should be made only from the thread that owns it. Although the window manager permits any thread to access such things as window properties, styles, and other attributes such as the window procedure, and such accesses are thread safe from the window manager's point of view, load-modify-write sequences should typically be restricted to the owner thread.
You could use SetWindowPos with the flag SWP_ASYNCWINDOWPOS, instead of MoveWindow.
The reason may be that ThreadA waits for ThreadB to handle some event but meanwhile ThreadB wait for ThreadA (the thread owning the window) to return the result of MoveWindow.
I think that @1800's explanation is the closest yet.
When you move a window from a thread that does not own the window, I think that Windows does not use SendMessage to deliver things like WM_WINDOWPOSCHANGING to the window procedure of the moved window. Instead, to ensure that the window procedure is only called on the right thread, it posts the WM_WINDOWPOSCHANGING message and blocks untill it's picked by event loop running in the right thread. However, that event loop is not running - it's blocked, waiting for MoveWindow to complete.
The solutions from @totaland and from @Logan Capaldo will work.
May be you don't need to wait until your window has moved. Or, if you do need to be sure, use MsgWaitForMultipleObjectsEx and run a small event loop to process posted messages.