I have an application that message-loops using MsgWaitForMultipleObjects to catch additional events while pumping ui messages. It seems that as soon as a window is being moved or resized, DefWindowProc begins it's own message loop until the mouse is being released. This situation prevents from the outer loop to catch the additional messages in the meantime.
I'd hate to multi-thread the application just because of this. Is there any other way to solve it?
MsgWaitForMultipleObjects has very few uses in a traditional multi threaded program. It has some use in Games - where traditional non client frame elements are omitted and APIs like "MessageBox" and "DoDragDrop" are avoided...
Usually it finds its best use in "UI worker" threads that don't host visible windows, but use the message queue as an inter thread messaging system and also need to wait on kernel handles.
In your case, making a second thread does not seem avoidable. Ironically, PostThreadMessage + MsgWaitForMultipleObjects will probably be the easiest way to set up a reliable communication mechanism between the GUI thread and your "ui" worker thread.
There are several additional places in the Windows API that will enter their own message loop. If you need to continue handling your messages during these times then you'll need a separate thread.
Related
I am fixing a MFC applivation written in C++. It is a GUI and it communicates with an external module connected to the PC via USB.
I want to avoid using a separate thread. Is there a way I can add things to the mainloop so that it runs continously rather than being event based?
I want the mainloop to make a call to a function runCommStack() in every loop.
Some possible approaches:
You can use CWnd::SetTimer to set a timer.
You can override CWinApp::OnIdle (called by CWinApp::Run).
You can override CWinApp:Run, copying and modifying the original MFC's CWinApp:Run. This definitely is not the easiest solution.
You can create a background thread.
It depends on the requirements of runCommStack(). Is this function running long times? Then you probably won't want to run it in the GUI thread. Does runCommStack need to get called every n milliseconds? Then it might also be better to run it in it's own thread. In other cases you can just use the timer or OnIdle approach.
Regarding solution 1: as Tim pointed out WM_TIMER messages are low priority messages and will not be passed to the application while other higher-priority messages are in the message queue. See also Determine priority of a window message.
With solution 2 you should remind that OnIdle will only be called if no window message is available. So this is quite the same as solution 1 (in fact a little worse).
Also keep in mind that solutions 2 and 3 might result in your runCommStack not getting called if a dialog's DoModal() is called or if a message box is displayed. This is because during MessageBox() the control is not returned to CWinApp::Run().
I'ld implement solution 1 or 4.
When there are no messages (like keys, mouse, repaint) arriving the main loop suspends the program, waiting for the next message. So the idea of adding a call to the main loop will give you very erratic operation. For example, minimizing your window will stop all the USB communication.
Using SetTimer and calling your runCommStack function in a WM_TIMER handler will probably be much more satisfactory.
You can use idle processing with CWinApp::OnIdle; this will work if reading your USB device takes only a short amount of time, otherwise the user interface will be blocked during long reads.
But using a separate thread is definitely a better method.
I have a DirectShow filter written in Delphi 6 using the DSPACK component library. It is a push source video filter that receives its source frames from an external cooperating process that I also wrote.
When the worker thread that calls my Filters' FillBuffer() call is created and ran, when the graph starts up, the first thing I do from that worker thread is create a hidden window using AllocateHWND() to process WM_COPYDATA messages that contain the externally generated frames. Right before the thread is destroyed I destroy the hidden window. In other words the hidden window is created and destroyed in the execution context of the worker thread that calls FillBuffer(). My intention is to let FillBuffer() block as it waits for a WM_COPYDATA or a WM_QUIT message. The external cooperating process will submit frames to my filter using a WM_COPYDATA message and the handle to my hidden windows' WndProcc(). I will post a WM_QUIT message in my override of the pin's Inactive() method (thanks for that tip #RomanR), to unblock the FillBuffer() call before the filter is shut down.
My question is, is it safe to call PeekMessage() or GetMessage() from the FillBuffer() call given this scenario? Or are there potential pitfalls that may arise from this occurring in the context of a DirectShow graph executing? Also, do you see any flaws in my overall approach here that I need to consider?
Safe, but not so reasonable too. FillBuffer is being called on a background worker thread which is typically have no windows on it. It would be perhaps only your window which you are going to implement message loop for. And the window is here only for the purpose of receiving WM_COPYDATA messages. It sounds like it can work out, but you would perhaps could do much easier without helper windows by passing your data between applications via named file mappings and events. In case of video (you have audio, right?) you would also be able to appreciate a smaller performance overhead.
Does anyone know where is the best place to forward thread messages to child controls?
Basically, app has to catch registered thread messages in range msg_frst...msg_last and forward them to active frame/view.
There are 3 overload points in MFC, or so it seems:
DefWndProc
OnWndMessage
PreTranslateMessage
Which is the correct one to override?
A message posted with PostThreadMessage() has a NULL window handle. So forget about any of the window methods, DispatchMessage() isn't going to deliver them. All you got is CWinThread::PreTranslateMessage().
But there's a big hazard here, this isn't going to be called anymore when any code in that thread start pumping its own message loop. Your messages now fall in the bit bucket because other code is now calling Peek/GetMessage(). That's a lot more likely then you think, MessageBox() is enough. Or the COM modal loop. Etcetera.
You can only safely use PostThreadMessage() to send messages to a thread that does not create any windows of its own. The workaround is simple enough, provide the thread with a window handle so it can call PostMessage() instead. That could be a hidden window, dedicated to handling these messages for example.
I have a thread that needs to dispatch a message (a simulated mouse event that it sends using SendInput) as soon as it's generated. I want this to happen in a loop where there is no sleep; adding any sleep hurts performance as I basically want the events to go in to the event loop immediately once they have been generated. Of course I also don't want the loop in the consumer thread to hog all the cpu so I can't just keep it running, although this gives me good performance.
As far as I understand this, the task is to make the consuming thread to wait for something that signals that the producing thread has provided something to dispatch (?) but how to best do this? I think I need something like two mutexes if I want to make the two threads mutually exclusive; consumer waits for the producer and the producer continues as soon as the consumer resumes running? Didn't really get this working so far and I'm really not sure how to best do this; CriticalSections vs. mutexes, something entirely different?
The reason I don't want to call SendInput from the producer thread is that that thread (the 'main thread'?) actually runs in response to a mouse move message, intercepted by a mouse hook, and sending more mouse messages from that thread didn't allow the thread to finnish before the simulated mouse move event was processed, messing things for me. As I suspected, moving the SendInput call to another thread so that the original thread could finish out of the way fixed the problem but now I need to make the consumer more responsive; mouse messages keep coming at a good pace I suppose since just a 1 ms Sleep made the loop too slow and message processing started lagging; all works well if I have no sleep.
Thanks.
Sounds like you want to use win32 event objects instead of mutexes or critical sections. See the docs here. The event functions allow a thread to wait on a condition that can be signaled from another thread.
Windows threads support message queues - usually used for windows messages but completely usable for messaging between worker threads. PostThreadMessage can be used in the Hook Proc to post messages to another thread for processing.
The worker thread can do a normal GetMessage loop to extract messages to process - rather than passing them on to DispatchMessage as you would in a UI thread you simply check the HWND is NULL in the message structure indicating its a thread message, then process the message yourself. In the case of potential message flooding PeekMessage can be used to cull any outstanding messages from the queue.
I wish to launch a separate thread for handling window messages (via a blocking GetMessage loop), but still create the windows in the initial thread, afterward.
Within the separate thread, as soon as it launches, I am calling PeekMessage with PM_NOREMOVE to ensure a message queue exists (is this necessary?), followed by..
AttachThreadInput(initial thread id,GetCurrentThreadId(),true)
..before finally entering the message loop
I am not yet using a mutex or cs to ensure this is happening in time, but am merely using a Sleep statement in my initial thread for the sake of simplicity.
Regardless, window messages do not appear to be intercepted by the separate thread.
I am a little unsure as to whether I am doing this correctly, and would appreciate any possible guidance. Both threads are in the same process
Thank you all
That's not what AttachThreadInput does. Even after you attach your input queue to another thread, Windows still have thread affinity. Messages in the queue for a given window can only be removed from the queue by that window's thread.
What AttachTheadInput does is to make two threads share an input queue. This allows them to query information about the input state and know that the other thread will get the same answer for the same query. For instance, one thread could call GetAsyncKeyState and know that the answer reflected the key state for the other thread.
It allows two or more threads to have the same relationship to the input queue and each other as processes had in Windows 3x. This is the reason that this API exists; so that complex multiprocess applications could be ported from Win 3x to Win95/WinNT.
It seems the best way to instigate window creation from the main thread, while having messages for them handled in a separate, looping thread is to use a custom message, that can be sent to the separate thread - Thus allowing it to create the window, but still allowing that action to be invoked from the initial thread:
1) Allocate a custom message, and create a structure to hold the window initialisation parameters:
message_create_window = WM_USER + 0;
class Message_create_window{
Message_create_window(...);
};
2) Instead of calling CreateWindow(Ex), use something similiar to the following, passing in the relavant window creation parameters:
PostThreadMessage(
thread.id,
message_create_window,
new Message_create_window(...),
0
);
3) Handle the custom message in the message pump of your ui handling thread, extract the creation parameters, & free afterwards:
MSG msg;
GetMessage(&msg,0,0,0);
...
switch(msg->message){
...
case message_create_window:{
Message_create_window *data=msg->wParam;
CreateWindowEx(data->...);
delete data;
}break;
...
This does, however, have the following side-effects:
The window will be created asynchronously. If it is required that the initial thread block until the window is created (or, indeed, that the window's existence can ever be asserted) then a thread synchronisation tool must be used (such as an event)
Care should be taken when interacting with the window (it is a multithreaded application, after all)
If there are any major holes in this answer, or this seems like a terrible approach, please correct me.
(This is still my question, & I am trying to find the best way to accomplish this)