We help IT Professionals succeed at work.

C++ sendng messages to GUI controls from different threads (thread - safety)

thready
thready asked
on
520 Views
Last Modified: 2012-05-11
Hi Experts,
I would like to set my mind straight on this once and for all.  When calling GUI controls from other threads, I know you have to send messages.  Can thIs be the case for non-GUI objects?

As an example to help answer this question, I'm writing a progress bar control that I want to have the method "SetCurrentProgress(CString strText, double dPercentProgress)".  I primarily want to know how to make this function thread-safe, and easily accessible to my whole application (I guess making it global is the easiest/best way for easy access?)

My usual approach is to have a SendMessage call within the SetCurrentProgress function so that the message is sent to the window of the progress bar and ends up being on the GUI thread instead of whatever the calling thread is on.  But my progress bar doesn't update.  So I try doing MessageQueueHelper::DoEvents to force the events in the event loop to occur, and this seems problematic as well.....  I've had this kind of thing more or less working nicely before, but I really need to know the best way, and understand what's going wrong exactly when things don't seem to work.

Thanks for your help!
Mike
Comment
Watch Question

CERTIFIED EXPERT
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
Todd GerbertSenior Engineer
CERTIFIED EXPERT
Top Expert 2010
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION

Author

Commented:
You're right tgerbert- there will often be situations where SendMessage will block and cause deadlocks.  Thanks HooKooDooKu, your answer is very thorough, but there's the key element I'm still missing- where do I put the SendMessage call?  I'm creating a progress bar and I want to 1) have easy access throughout the program to the progress bar and 2) not have to worry about calling PostMessage - I'd rather call a nice function that will call PostMessage for me...  This seems easy, but I always have some trouble with it.  Like now, I have my progress bar as a global variable and the program is crashing in RegisterWindowClass (custom control stuff) on the call to AfxGetInstanceHandle() - because current instance handle is null by making the progress bar global...  I don't understand.

So I revert to using a class variable in the parent dialog instead of making the progress bar global and now I have to worry about how I need to give my thread access to this-- which I find makes things a mess.  Globals are not the most kosher thing in the world, but they are definitely cleaner than the alternative.  After all, my app only has 1 progress bar.  Anyway.  So now I'm trying to figure out how to give this thread access to my progress bar in the most elegant way possible.

Thread (for testing my control)
    for(int i = 0; i < 100; i++)
         SomehowGetProgressPointer->SetCurrentProgress(i);

inside ProgressBar::SetCurrentProgress(int nProgress)
        PostMessage(WM_PROGRESS_UPDATE, 0, nProgress)

ON_MESSAGE(WM_PROGRESS_UPDATE, OnProgressUpdate)

LONG OnProgressUpdate(WPARAM wParaam, LPARAM lParam)
        m_nProgress=  (int)lParam;
        Invalidate();

Does this make sense?  Is there a better way?  How do I get access to the progress control in a clean way?

Sorry for the long-winded question - but this has been bugging me for far too long and I really want to make this clear for myself.

Thanks a lot for your help with this gentlemen!

Mike

Author

Commented:
There is one alternative that I currently use that I don't like.  I just send messages and I keep a pointer to the window handle of the object that handles the message...   I just wish there were a better way....

Author

Commented:
... a more object oriented way...

Author

Commented:
After reading more about this online, I think it's actually better to pass HWNDs instead of accessing actual objects - it's a better way to decouple the GUI from the work being done.  So this ends this question and I'm satisfied.  Thanks again!
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.