I have an application which processes certain data, and displays that in a UI.
Initially I had just a single thread, the main process, doing the work, i.e., retrieving the data for processing, processing the data, and then updating the UI. The data resides on another server.
However, the requirements for the application changed, and much more data has to be retrieved from the server and processed than previously thought. This is creating performance issues, since data has to retrieved, processed and then the UI has to figure out where it should be put
The UI is CListCtrl based MFC controls.
To combat this, I have split the processing n two threads, one which acquired the data and processes it, and another which will display it, i.e. the GUI.
I need some way to signal the UI thread, that the data has been fetched and processed. The thread is created using CreateThread. What is the best way to signal the other thread that it can do its own job?
I suggest the following: when your separate thread has to notify the GUI something you should call a PostMessage to the window containing the controls.
The message param should be a user defined message so something defined by you e.g.
#define WM_MYMESSAGE (WM_USER + 1)
The other two params (LPARAM and LPARAM) will contain data you need to pass to the GUI. So in CreateThread you need to pass some info about the window that will receive the message (the CWnd pointer if you use MFC, HWND handle otherwise).
Then you need to handle this message inside you window (see references about ON_COMMAND and the like macros)
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?
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.
In my MFC application , I am using TCP/IP socket for communcating and getting data from a server.During this process I am displaying a modelless dialog with static text and progress control.During communication I am updating the static text and progress control in a separate user thread(AfxBeginThread).
If I try to communicate to wrong ip the sockets select function with timeout value 5 secs blocking the displaying of dialog with static text and progress control(I.e the dialog hangs, the controls are getting displayed).
Once the socket comes out from select function the dialog is getting displayed properly.
How to fix this problem?
In MFC, I'd strongly recommend using CAsyncSockets, and just reacting when data comes in from the server. You probably have no need to spin up a thread at all.
If you were going to spin up a separate thread for part of the job, you'd want to allocate tasks to threads somewhat differently. You always want to leave UI updates in the main thread (the one that was created by default). If you were going to use (for example) a blocking socket, and call select on it, you'd want to move that work to a separate thread, and leave the UI updates in the thread that was created by default. Then the thread handling the socket could (for example) send messages to the UI thread to tell it about what's going on, so it could update the UI appropriately. But, as already noted, you probably just want to use a CAsyncSocket, in which case you won't need a second thread at all.
I would like to access drag slider control of my dialog box from worker thread. I read many warnings regarding accessing main window controls from worker thread. Since they have a high chances of resulting in a dead lock. In this case, how to access the control using messages? I know how to create user defined messages (WM_USER) and write our own handlers. What it would like to know is that is there any system defined message for each controls and if it is there, how to post those messages to access the control?
You can use PostMessage to send a message to the control and the main UI thread will actually dispatch the message to the control, ie the work will happen on the UI thread (assuming the UI thread is pumping messages). Looking at afxcmn.inl you can see what SetPos is doing:
_AFXCMN_INLINE void CSliderCtrl::SetPos(_In_ int nPos)
{ ASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, TBM_SETPOS, TRUE, nPos); }
Changing that for PostMessage:
::PostMessage(hSlider, TBM_SETPOS, TRUE, nPos);
If you want something more complicated post a WM_USER message to a the parent window and handle your control managing functionality there because, again, the WM_USER message will be dispatched by the UI thread so you can work with your control safely.
I have a multiple dialog MFC client app that i am working on. This client can receive a lot of messaging (>10Hz) to the main dialog, which often performs some small function, then forwards that message onto the another dialog for processing.
In my specific case, the main dialog receives messages relating to a vehicle location, updates a couple fields on that GUI, then passes it on vi a PostMessage to a window that displays all the vehicle information.
So basically, my question is this: what is the difference b/w posting the message, or just calling the dialog.update (which is a function i created)?
Well, since we don't know what your dialog.update() does, how are we to know what the difference is?
If you are doing another PostMessage, I'm not sure what the point of that is. Your program has to wait for another iteration of the message loop to retrieve your newly posted message and possibly another message could be received before that one is posted. Instead of PostMessage, you could use SendMessage which will send the message straight to the WndProc without having to iterate the message loop for another message.
I am thinking that if you are multi-threaded, then sending or posting messages will be a little more thread safe since Windows should switch contexts automatically. If you are single threaded, then it probably shouldn't matter.
I believe your application is multithreaded, and one of the thread is receivng the data, and is different than GUI thread. You should use PostMessage only from other thread to this dialog, and not SendMessage or direct call.
If you are receiving too many messages, you should buffer them - either by count (say 5000), or by some timeout. You may keep the messages into vector, list or any other collection you like. Later, when sending, post the address of this collection as WPARAM (or LPARAM) to the dialog. Dialog will get it, in a single bunch and would process it. This approach may not be correct as I am not aware about other design perspetives of your application.
You would need to trial-and-error approach, see where you get the actual performance and stability benefits.