I'd like to create a window on one thread, and then have that HWND migrate to one of any number of threads on which it will execute. My program will have multiple such windows. Is this possible or was the Win32 API not designed for this?
Yes, to a certain extent.
You can send and post messages to an HWND from any thread.
http://msdn.microsoft.com/en-us/library/ms644944(v=VS.85).aspx
Attempting to configure the UI (e.g. add controls) from another thread will end badly. However, if you send your window a message, you can be sure that the message will be processed on the creating thread.
No, this is not possible. The thread that a window uses for its message loop (what you refer to as "executing on") is defined at the time the window is created. You can create multiple threads and start message loops from them (and thus create windows on them), but this is generally regarded as dangerous.
There are two important calls that must be called from the same thread: CreateWindow and GetMessage (or their respective equivalents). Your solution wouldn't, so it's wrong.
You may call PostMessage in any thread. SendMessage is somewhat dangerous because it blocks in cross-thread scenario's, and could deadlock.
No, there is no concurrency checking on those calls.
Related
I'm using a dispatching mechanism in my Win32 application where non-main threads can post a piece of work wrapped in an std::function for later execution on the main thread. This is realized by creating a hidden window from the main thread, and using its window procedure to filter out these pieces of work, and then executing them. Background threads then use a PostMessage() call on this window, with a custom message id (>WM_USER), while wrapping a heap-allocated std::function in the LParam.
This approach appears to be conceptually sound, but I have some reservations regarding thread-safety. MSDN makes no mention that I found, indicating whether multiple threads may or may not simultaneously post a message to the same window. Is there a definitive verdict?
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.
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 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.
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.