Click here to Skip to main content
15,888,401 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am building a custom data structure that is a binary tree of objects and binary trees. ie: each node in the top level tree could be an "object" or an "objectContainer" (which in turn could have "object"s or "objectContainer"s for nodes).

I have a message pump in my main thread, through this pump I handle all the windows messages intended for my main window (clicks, drags and resizing, button presses). And when it is not dealing with windows messages it ticks a timer and updates the scene. When the main window receives a specific key stroke it (currently) spins off a new thread, that thread then creates a new object (or objectContainer) and, during the new object's creation, a modal (blocking) dialog box is spawned so that the user can interact with/input initial values for the newly created object. Upon clicking OK, if the name provided is unique (with regards to the contents of the top level container), the new object is added to the top level container. Finally, if a modal dialog box (spawned from inside yet another thread) that displays the contents of a (in this case the top level) container, is open, I send a WM_message to said dialog box that is intended to tell it to add the new item's name to a list box of strings. I am having issues with the sending of these messages to dialog boxes. For instance, when I create an objectContainer the correct name appears in the list right away after pressing the OK button, but not if I am creating an object. I assumed it may have something to do with threading, but I do not know. Each type of object uses the same addObject() function, which is where the container's displaying box is tested to be open or not and the message is sent.

What I have tried:

I have read articles that say never use threading… unless you absolutely have to! And that all UI should be done in the same thread. Some even say to only do UI through the main thread. I have tried variations of my application with some of the techniques I feel like the authors of these articles are suggesting but something is not right.

I made a version in which, when the button is pressed, the main thread spawns a modeless dialog that does the work of interacting with the newly created object. This works well except for, if say the user is dragging around a modeless dialog box for a long period of time, the main process gets stalled. I have a function after the IsDialogMessage part of the main message pump that calculates frame rate and it tanks when the modeless dialog box is clicked and held by the user. I don’t think I want that happening, the functions that update the scene are not run until the user lets go. (come to think of it, if i drag around the main window the frame rate processing stalls too... but i suspect that is unavoidable, right? unless that processing is in its own thread...?)

I have also created a version where once the button is clicked the main thread spins off a new thread, the new thread creates the new object or objectContainer and right after the new item is created it spawns a modeless dialog box to editObject(). With the modeless dialog box the calling thread is not blocked and so I added a message pump directly after the creation of said modeless dialog box and it appears to be working. I have not yet tested past the adding of the objects and verifying that the name is unique in the top level container. I do not know if the wm_messages will reach the correct window and control the dialog box's string list box as I wish.

I am having issues with each of my design attempts and would just like to know your thoughts on design before I waste more time debugging a bad design. Should the main thread spin off a thread and call a modal dialog box? Or should all dialog boxes be called from the main thread and I, somehow, move what I think needs to be continually processing to its own thread? Or should the main thread spin off a thread and then use modeless dialog boxes?
Posted
Updated 31-May-17 4:43am
v3
Comments
Richard MacCutchan 31-May-17 4:41am    
If you are determined to use threads then you need to add a mechanism to synchronise the events when creating your objects. If thread A spawns thread B then they run independently, but there is no guarantee which one will complete any of its tasks first. Read up on the use of semaphores to synchronise tasks.

1 solution

Hi,

Have not heard of this problem for nearly a decade. :)

I would recommend that you keep all 'window creation' and 'window management' in the main thread. Modal windows may be eating your thread messages.

Rescuing thread messages from modal loops via message filters[^]

Thread messages are eaten by modal loops[^]

You are indeed looking at a bad software design... be careful because some of these message eating bugs happen less than 1% of the time... if this is commercial software you may have hundreds of customers complaining of bugs while you are sitting in your office saying "It works for me!"

Avoid launching a modal dialog from a worker thread if you expect the thread to be able to receive thread messages. Instead... have your non-GUI worker threads post a message back to the main thread and allow that thread to create/manage ALL windows.

Best Wishes,
-David Delaune
 
Share this answer
 
Comments
brokkster 31-May-17 13:15pm    
very interesting. message eating bugs... terrible.
and i assume modeless boxes spawned from worker threads is a non-starter too? (sure they are; keep UI in the main thread.)
i am a decade behind? maybe i can take a class.
thread messages... i've been use SendMessage and not PostMessage(if that even matters at this point), i assume if worker threads are communicating back to main thread, it's going to have to be PostMessage, no?
thanks for your help.
-scott
[no name] 31-May-17 13:57pm    
Yes, you are more than a decade behind. You appear to have reached that point in Win32 development where you have just enough knowledge to get yourself in trouble.

Read all of this:

https://msdn.microsoft.com/en-us/library/ms810439.aspx

(Note the date of 1993)

Scroll down to these parts:
How Multiple Threads Affect Window Management
The Effects of Multiple Threads on Message Routing

There are some things that are not mentioned in that document...

When you do this from a worker thread:

mainThread->DoSomething();

Guess where all the window messages for your worker thread are going? To your main thread for the duration of the call.

Don't ever reach across threads to execute code from a GUI worker threads.

Follow these rules:
1.) Only create and manage windows from your main thread.
2.) Never reach across GUI threads to execute code: somethread->DoSomething(); Instead Post a message to your thread instructing it to DoSomething();

brokkster 2-Jun-17 12:54pm    
thank you.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900