I need to run message loop in other thread using std::async, is it possible to get messages from main thread? Can you give some exampels?
And second question: i do not need to call wndproc, what i need is just getting messages and avoid "program not responding", do i need to call dispatchmessage()?
Each thread manages its own message queue. If you want the main thread's messages, the main thread must get them and post them to you. But it sounds like that would defeat the purpose altogether.
Sounds like what you really want is to switch your threads' places. Have the main thread run your message pump and do your intensive processing on another thread.
As for DispatchMessage, you can get by without it if you don't have a window. But if you do, you should call it. You have to handle window messages in order to appear responsive, and it hides some of the details of doing so.
Related
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 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 situation where I want to SendMessage to a window that was created on another thread than the one that is calling SendMessage.
The default behaviour seems to be block forever and not work.
So I changed the call to PostMessage, which didn't block the sending thread, but the message never appears to arrive at the intended window.
So how do I SendMessage to a window created on a separate thread, or is this impossible?
The PostThreadMessage function posts a message to the message queue of the specified thread. you can specified Identifier of the thread to which the message is to be posted. is that you want?
What is the thread that owns the target window doing? It needs to be pumping messages in order to be able to receive messages that are either sent or posted to it. Typically this is done by having a GetMessage/TranslateMessage/DispatchMessage loop. If the thread is doing something else - such as blocking waiting for an event or mutex or IO to complete, or is busy in some other loop carrying out a calculation, it won't receive messages: SendMessage to the thread will block, and PostMessage will post but not get delivered.
If that target thread needs to both manage events or similar, and it also owns a window, you may need to use MsgWaitForMultipleObjects in that thread's message loop.
You are running into a deadlock. An example, if you SendMessage to another thread, then the windowProc in that thread does SendMessage back to your window, they will lock waiting each other forever.
You need to either fix PostMessage (it does deliver messages, there's just error in your code somewhere), or be very careful about who calls who and when.
To protect against threads that are busy or hung, there is SendMessageTimeout.
Each control you create belongs to the thread that created it, which means that the WndProc for that control will be running in the thread that created the control. You send messages with SendMessage and PostMessage freely to any control.
The issue with CWnd::PostMessage and CWnd::SendMessage is the same. The message is being pushed out, and not being received by anything. SendMessage is blocking by design; it's job is to block the thread until the message is received.
MSDN says this about SendMessage:
"The SendMessage function calls the window procedure for the specified
window and does not return until the window procedure has processed
the message."
It is possible to send a message to window on another thread using CWnd::PostThreadMessage or winapi PostMessage. When you create the window you can use GetSafeHwnd() to get the handle or you can use a thread ID when the thread is created.
I am working on a MFC project where I need a separate loop that will run continually or once every few seconds, and each time it may or may not need to run a Dialog to get some input from the user. I was thinking of using AfxBeginThread, but from what I have read about it, it doesn't really work with a continuous loop.
Don't do it. You can't just rip dialogs off in worker threads. They can only be started in the main thread, because they need the message pump in order to function.
If all you want is a signal of some kind that fires every few seconds, then what you want is a timer. Set the timer for the timer period you want, and when your main thread processed the desired WM_TIMER message, you can pop up a dialog and do your thing.
If you want your worker thread to do some work, which may or may not include asking the user for information, then you'll want to look in to having your thread use PostMessage() to send a message to the main thread, process that message int he main thread by asking the user for data, and then sending a signal back to the worker thread with the input data. One way to accomplish the last bit is by calling QueueUserAPC() from the main thread with the worker thread's handle and a pointer to a function that does somethething with the newly-entered data.
Is there any API to send message to a thread?
Basically I have only threadId available and I want to send a custom message to that thread.
PostThreadMessage. Not very reliable though.
See The Old New Thing blog here and here for details on why. Basically modal message loops make a mess of the whole idea. Since a message posted to a thread has no window handle, calling DispatchMessage will throw the message away. Any modal loop you run - directly or indirectly - will call DispatchMessage, so a good proportion of the time this strategy will fail and your message will disappear into the ether.
you can use QueueUserAPC if the target thread is alertable