Which thread calls the windows proc callback function? - c++

I am a bit unsure which thread calls the wndproc callback function. Is it the main thread from the application, like in the message loop or is a seperate windows thread ? The function has access to class objects and I dont want there to be any corruption of data if 2 thread happend to access the class object at the same time.

Yes, it is main thread of application.
An application's main thread starts its message loop after
initializing the application and creating at least one window. After
it is started, the message loop continues to retrieve messages from
the thread's message queue and to dispatch them to the appropriate
windows. The message loop ends when the GetMessage function removes
the WM_QUIT message from the message queue.
Source: About Messages and Message Queues

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.

How to get message from other thread winapi

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.

How do I SendMessage() to a window created on another thread?

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.

Run windows GUI application in synchronized mode?

I am debugging GUI app on windows and I want to find out who is the sender of some message. On linux, I can run app in synchronized mode and find the sender in call stack. Is there any equivalent mode in windows?
AFAIK there's no built-in ability to do this.
But let's first investigate the problem. You want to know who's the sender of the message. You should know however that windows message processing can be classified by the following criterias:
Posted vs Sent messages (PostMessage vs SendMessage).
Messages sent to the window belonging to another thread vs sender thread.
Messages posted to a thread (not bound to a specific window, hence not processed by the window procedure).
You may trace directly the sender only when the message is sent (not posted) to a window, whereas the call to the SendMessage (or similar) was issued in the thread to which the window belongs. In such you will see the sender in the call stack.
In case the message was sent from another thread - you will not see it in the call stack. Simply because the call stack shows the call chain that belongs to the current thread only. When a message is sent from another thread the system performs the following:
Suspends the caller thread.
Puts this message to the queue of the thread that owns the window.
When that thread calls GetMessage (or similar) - the message is dispatched to the window.
Finally the OS resumes the caller thread. The SendMessage returns with the result that was returned by the window procedure.
In such a case you may try to identify the caller indirectly. Interrupt your program with the breakpoint, and try to search for suspended threads, which are blocked in a call to SendMessage or similar.
Finally, messages that are posted are impossible to trace by the above method. You may try to put a conditional breakpoint on a call to PostMessage, but if the caller belongs to another problem - this will be more complex.
valdo is correct. Calls to SendMessage call your applications wndproc directly. Calls to PostMessage posts the message to the message que and your application then recives the message via the message pump (the loop, getmessage, translatemessage, dispatchmessage). So , like he said, if the messages were sent via a SendMessage then the callee of the function will show in the call stack. If it was sent via PostMessage , it will not.

Why is my DCOM client locking on a call to SendMessage?

Running on XP. I have a client that calls calls CoInitializeEx(NULL, COINIT_MULTITHREADED), loads a (local) DCOM object, and attaches an event interface so the DCOM object can send back events. The client looks a lot like notepad with a multi-line textbox covering the client area to display event messages. Here are the calls that create a lock-up:
Client calls p->DoStuff() on the DCOM object.
The DCOM object calls c->DoStuffEvent() on the client while processing DoStuff().
The client sends a EM_REPLACESEL message to the child textbox to have it display "stuff is happening"
The client freezes on the SendMessage(EM_REPLACESEL). The client's call to p->DoStuff() is done on a the main thread while the SendMessage(EM_REPLACESEL) is done on a different thread. I'm sure this has something to do with the problem.
Can someone explain what's causing the lock and how I might work around it? The client and DCOM objects are coded by me in MSVC/ATL, so I can modify them both as needed.
It would appear that the window was created by the main thread. So that is the only thread that can call the window proc. When you SendMessage from the other thread, what it actually does it to put the message into the main thread's queue and then wait for the main thread to call GetMessage or PeekMessage. Inside the call to GetMessage or PeekMessage, Windows notices a waiting cross-thread SendMessage and passes that message to the window proc, then it wakes the second thread and lets it continue.
If you don't care about the return value of SendMessage(EM_REPLACESEL), you can use SendNotifyMessage instead. But if you do this, you need to make sure that the string you pass with the EM_REPLACESEL message is still valid when the message is finally delivered.
As per the SendMessage documentation, SendMessage does not return until the function is completed. It is synchronous. I believe it is always answered on the UI thread as well. If you want to do an asynchronous message pass, then you should use PostMessage.