MoveWindow deadlock? - c++

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?

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.

What is the "some sort of sync mechanism"? If it is WaitFor(Multiple)Object(s), you can use [MsgWaitForMultipleObjects](http://msdn.microsoft.com/en-us/library/ms684242(VS.85).aspx)(Ex instead to wake up when you have a message and dispatch it as Lucero suggests.

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.

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

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.

Related

Window procedure and CreateWindowEx function

Does the Window Procedure specified as lpfnWndProc by window class during registration runs in a separate thread ?
There is an important concept in windows called the message loop.
It is usually inside the main function (aka: WinMain) and can be characterized in the following manner:
while (true) {
// blocks until there's a new message to process
GetMessage()
TranslateMessage()
// ends up calling the propper WndProc callback
DispatchMessage()
}
Update: When you create a window, the thread on which the window is created owns the windows (and the its message queue). Therefor, it must provide the message loop process. This is usually done in the application's main thread but, as other user stated, it can also be done in a separate thread.
The function DispatchMessage takes care of executing the WindowProc procedure of the window targeted by the message (as specified by the message's hwnd parameter).
So, when you create a window, the lpfnWndProc parameter specifies where you want to be notified for events (mouse clicks, keyboard presses, etc). And it is always called in the same thread (the application's main thread or the one which owns the window).
A word of advice: If you need to perform a potentially long operation as the result of an event, you must create a new thread (aka background worker) for the task, and perform some kind of IPC to notify the main thread when the function is finished.
You can find instructions about how to write a windows procedure here. Also, there is some info about the main loop in this wikipedia page.
Does the Window Procedure specified as lpfnWndProc by window class during registration runs in a separate thread ?
No, it is called (as a callback) when events (aka messages) are dispatched by your message loop. In this way - the so-called 'event-driven' model - your program is able to react to user input as and when it happens without having to deal with any multi-threading or re-entrancy issues.
You might have more than one thread, but if it has windows associated with it (i.e. CreateWindowEx was called by that thread) then it would need to have its own message loop.

MFC: Is it safe to call CWnd methods from another thread?

Actually I have two questions:
Is it safe to call SendMessage from a worker thread?
Do CWnd methods, like MessageBox, call API function SendMessage behind the scene?
Per my understanding, when the worker thread calls SendMessage, it pushes the message into the message queue of the UI thread, and waits until this message is processed. In that case, it would be safe to do so.
I'm not quite sure about this. please correct me if I was wrong.
Thanks a lot.
------------------------ update ----------------------------------
As a conclusion:
It's safe to call the windows API ::SendMessage and ::PostMessage across threads.
It's not safe to call CWnd methods across threads. Some of the methods may be safe, but it's not guaranteed.
Great thanks to everyone.
Is it safe to call SendMessage from a worker thread?
Yes. The system makes sure, that message handling is serialized on the receiving thread. When sending messages across threads, the sender is blocked until the message has been handled. The receiver only handles a cross-thread sent message when it executes message retrieval code (GetMessage, PeekMessage, etc.). Sent messages are never queued in the message queue. The documentation for SendMessage has additional details.
Do CWnd methods, like MessageBox, call API function SendMessage behind the scene?
Yes. For one, the message box will receive standard window messages like WM_CREATE or WM_NCCREATE as part of the dialog construction. Also, for owned windows (like modal dialogs), the system will send WM_ACTIVATE messages to both the window being deactivated, and the window being activated. I'm not sure why this matters, though, or why you asked this question in particular.
Now the question in your title:
Is it safe to call CWnd methods from another thread?
In general, no. It does depend on the member, though. Some are safe to call, others aren't. In particular, all methods that modify window state (contents, visibility, activation, etc.) should only be called from the thread that created the window. In case the call is not safe, the system will still be in a consistent state. However, your application may not be.
The ONLY way for a thread to access the UI is by using SendMessage or PostMessage.
Consider a machine with one core, where context switching occurs and you make direct access to the UI from a worker thread, you are potentially corrupting the UI thread registers !
Basically every UI framework offers a mechanism (many times several), for making UI changes from a thread. For instance Android offers an ASyncTask and a Handler.

How to divert a thread to post messages to a new window

I have a thread that I pass an HWND of a window where it post messages and updates a progress bar. The user can however go to another window (modal) where I would also like to show the progress of this thread. Passing the initial HWND is obviously straight forward but how can I divert the thread to post messages to the new window once its running? This is a c++ worker thread. I am using Windows 7,MFC, C++.
Put it other way around. Let progress windows get the address of the class from worker thread, and ask it periodically for progress. With timer, for example. That way, you will be able to have as much progress windows as you need.
There are two approaches. One is Daniel's way, that polls progress info from the UI window. All you need is a thread-safe 'int GetProgressPercent() const' member in the thread-implementing class (or equivalent free function).
The other approach is to use PostMessage or PostThreadMessage in the worker thread as progress happens and on the other end process the message adjusting the bar.
The main problem with either is to handle lifetime issues, prevent calls to object or HWND when it is actually gone already. For that the PostThreadMessage way is probably the safest baseline, as the main thread is supposed to be there and manage all the other threads -- and track the overall state of the program able to do meaningful dispatch to live windows or nothing. But it's the most complex too.

Z-Order of PopupWindow

I Created a LayerdWindow with WS_POPUP prpoerty set..
But I am not able to set it's Z-Order by SetWindowPos..This windows is always coming on the top of other windows. I want it below to a particular window..
My guess is that you are not calling SetWindowPos() from the thread where you created the window. Use the same thread or try this flag:
SWP_ASYNCWINDOWPOS
If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request.

How do I create Modal dialog in worker thread(Non-UI thread)?

I have written a sample MFC application in which there are two threads:
-Main thread ( UI thread)
-Worker thread ( non-UI thread)
I have a specific requirement to create a Modal dialog in Non-UI ( worker thread).
When I create the CDialog object and call DoModal on the same, it works. The dialog gets created and acts as Modal to the application. ( Win XP SP2 machine) But this does not work in Windows 2003 server machine.
The behavior in 2003 server is that, the Modal Dialog goes behind the application main Window and dialog will be brought to front only when I click on Main Window. It is not acting as Modal dialog to my application.
What could be the problem -- any ideas?
If creating UI controls in non-UI thread is the issue then is there any Win32 API which will allow me to link my worker thread to Main UI thread such that DoModal happens in Main thread. I tried AttachThreadInput but it is not working.
There is no reliable way to spread GUI modality across multiple threads. Every window is represented by an object referenced through a HWND which in turn has thread affinity. This is a left-over from the 16-bit days of Windows, where there was no multi threading. Consequently the HWNDs are not protected against concurrent access. The Old New Thing has an excellent series on "Thread affinity of user interface objects" (Part 1 2 3 Addendum).
Modality is implemented by first enabling the dialog window and then disabling its parent. The first step is safe while the second attempts to disable a window from a thread which is not the window's owning thread. Since en-/disabling windows modifies the object referenced through the HWND it represents a race condition.
The suggested solution is to confine your GUI to a single thread and communicate from your worker thread to the GUI thread to have it perform user interaction on the worker thread's behalf. The easiest way to accomplish this is to call SendMessage from the worker thread to block until the GUI thread's message handler returns. If the worker thread should continue to run while the dialog is displayed you could use PostMessage instead and communicate back to the worker thread using PostThreadMessage or signaling a synchronization object like an Event Object.
First of all, I'd like to agree with other posters that it's probably better to show the dialog on the main UI thread.
However, if you must, you can make a dialog on another thread modal with the following steps:
Pass your active window as an owner when creating the dialog.
When dialog is showing, iterate over your other windows and do them EnableWindow(FALSE). When the dialog is hiding, do the reverse. You will probably have to remember windows' enabled state and restore the original state, not just EnableWindow(TRUE).
Ensure that accelerators and other global commands will be ignored while the dialog is shown.
Note that (2) shouldn't be necessary provided that you do (1), but you've mentioned MFC, and I don't remember exactly how it behaves. It has it's own modal dialog implementation which may not exactly match Win32. If you're lucky, (1) and (3) will be enough.
While i don't know about the specifics of dialog handling on Server 2003, the simplest workaround to get on the main thread would be to use a custom window message, do ::SendMessage() and display the dialog in the message handler.
I recommend you not to do what the question subject suggests, and confine all UI to one thread. If you need the other thread to communicate with the user, create some messaging mechanism that will ask the UI thread to do it, and transport the results back.