tags:

views:

71

answers:

4

I have a legacy C++, MFC application, currently compiling in VS2005.

It has several socket connections, as well as a user GUI.

The sockets are terminated in non-MFC threads, some work is done in those background threads, then a message is posted to the MFC main queue so the main application can take notice and do the appropriate actions. Note that there is one message posted to the main thread for each socket-received message.

The main thread actions that result generally take a fraction of a second each.

If I receive a flood of messages, however, the GUI can become sluggish or even non-responsive for a period, as the main thread is busy doing the integrate-new-data tasks instead of responding to the user.

If I have managed to express my problem clearly: any suggestions for solutions, such that the GUI remains responsive in the face of a large number of these events?

+1  A: 

My own answer - don't throw anything too hard! :)

Idea is to break up the one-message-posted-to-main-thread per message to a more broken-up model.

If I have three background listening threads, then I should have three background queues, separate from the main MFC event queue. When I receive something, I post to the main MFC thread; and enqueue in the specific background queue.

When that specific event is actioned by the MFC main thread, I can act on some or all of the received messages in the appropriate background queue, and if I do not completely drain the queue, then I just repost a message to the MFC main thread to make sure I will wake up again to finish the job.

This ensures that the GUI events will be pumped at an appropriate rate, even under high other message rate receipt from the various background threads.

sdg
+1  A: 

Can you profile the code that is called in your GUI/Main thread. Are you sure you need to do the processing in your main/GUI thread? If possible, offload that work to another thread or pace the work being done.

Tim
Can you elaborate what you mean by "pace the work"? My "separate queues" idea seems to mean that, yes? Thanks!
sdg
Either the consumer (in this case the GUI thread) can process one message/command/whatever per time cycle or do something similar so that the GUI event queue does not get starved. This can be some kind of event or condition flag that is set when there are items in your event queue. Only process one in a row, unless there are no other events waiting.
Tim
+1  A: 

Instead of attempting to keep the GUI responsive in the face of a flood of events, you just about need to assure that it never gets such a flood of events in the first place.

On a typical computer, the screen is only re-drawn at 60 FPS, so nothing faster than that can hope to make sense. For a user, even 60 FPS only really makes sense for something on the order of a movie.

For typical data updates, 10 FPS is fast -- to perceive even that much, you need to summarize the data into a few pieces that are easy to understand, and avoid overwriting any existing text so it doesn't just turn into an unreadable blur.

Jerry Coffin
The GUI might not even change as a direct result of the received event, as it might only generate some internal book-keeping; but the data structures are (unfortunately) very close to the GUI, and are therefore maintained by that thread.
sdg
+2  A: 

If you want the GUI to take complete precedence over the socket work, you can use CWinApp::OnIdle to check for work to be done on the sockets.

Mark Ransom
Going to accept this one, as the highest voted. Not sure it is the path we will take, but thanks to all answer-ers and Mark.
sdg
@sdg, there's no need to accept the highest voted answer - you should pick the one that meets your own needs the best. The highest voted answer will always be just beneath it, so anyone coming back to this page will likely see both of them.
Mark Ransom