views:

213

answers:

5

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?

+1  A: 

You 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().

Lucero
If this is so, then why won't it get deadlocked when I call MoveWindow from within the same thread?
Because within the same thread, synchronous SendMessage calls wind up just calling the WndProc directly - they aren't sent via the thread's message loop.
Michael
Thanks Michael. It's important to keep in mind that each thread has its very own message queue.
Lucero
Yup, this is just what i suspected.So, is there any way to overcome this?I've tried simply posting a WM_MOVE message, didn't do it. I also tried to use AttachThreadInput on the two threads, but it still winds up deadlocked.
Are you using PostThreadMessage to post the message from thread B into A's message queue? Thread A must be weiting with a running message loop of course.http://msdn.microsoft.com/en-us/library/ms644946(VS.85).aspx
Lucero
I tried to post a WM_MOVE message to the child instead of using MoveWindow. Put shortly: is there a way to move a window asynchronously?
MSDN says: "MoveWindow sends the WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED, WM_MOVE, WM_SIZE, and WM_NCCALCSIZE messages to the window.". So my gess is, if you send those messages with the correct parameters using PostThreadMessage, it should just do what you want.
Lucero
+2  A: 

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.

Logan Capaldo
This one involves merging the two threads into a single one. Right now I'm trying to avoid that.
+1  A: 

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.

1800 INFORMATION
A: 

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.

total
A: 

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.

Arkadiy