Click here to Skip to main content
15,889,281 members
Articles / Desktop Programming / MFC

MessageBoxes and worker threads

Rate me:
Please Sign up or sign in to vote.
4.57/5 (6 votes)
25 Oct 2010Apache3 min read 44.5K   9   8
MessageBoxes and worker threads

This will hopefully become a more organized article with code samples, but I need to record my results for now. Here’s the practical problem I encountered in the application I am working on: several message boxes initiated by worker threads would pop up simultaneously confusing the user and wrecking havoc.

So, the task is: you want to display a notification (message box) from a worker thread. Sometimes it is fire-and-forget, sometimes you want to know the answer (“Do you want to continue? Yes|No”). I will assume the answer is important, since this case is more complicated.

Here are some facts that I discovered:

Fact #1: Dismissing a message box may enable the parent even if there are other pending message boxes. I am not sure what is the exact algorithm here, but if you have multiple message boxes on the screen, there is at least one of them that would re-enable the parent when dismissed. This will render all other message boxes effectively modeless. The user can continue to work on the parent and maybe even create more message boxes.

Fact #2: Calling MessageBox() from a worker thread effectively converts that thread to a UI thread with the message pump.

Fact #3: If the UI thread is blocked, MessageBox() will also block, even when called on a worker thread. The reason for that is that MessageBox() internally called DialogBox2() function in user32.dll, which calls NtUserCallHwndParamLock(). I am not sure what that function does, but it blocks if the UI thread does not respond.

Fact #4: If you use PostMessage (BeginInvoke) or SendMessage (Invoke) to render the message boxes on the UI thread, the message boxes can still appear in parallel. In fact, they become recursive. If you look at the call stack, it looks like one message box calls another.

This happens because the parent window is not dead while showing a message box: it is just disabled. The message box runs its own message pump, and when another thread sends a message instructing the parent window to show another message box, it will be happily processed, showing the second message box on top of the first.

Bottom line: “serializing” message box calls via PostMessage/SendMessage to the UI thread does not work.

Fact #5. If the UI thread is blocked while we send it “show that message box” messages, the message boxes will appear in sequence, starting with the latest. This puzzled me for a while, but after some research, I found the truth. The message boxes are still being called recursively, only they don't have a chance to show. Showing a window is a complex process that requires handling multiple WM_ messages. When MessageBox() function is called and starts running the inner message loop, there is no window yet. It will appear a little bit later. However, the first message that is processed in the new loop is a request for another message box, which effectively defers creation of the window until later. Only the last message box in the chain has a chance to display itself. Once it is dismissed, previous message box(es) take turn.

This article was originally posted at http://www.ikriv.com/blog?p=610

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0


Written By
Technical Lead Thomson Reuters
United States United States
Ivan is a hands-on software architect/technical lead working for Thomson Reuters in the New York City area. At present I am mostly building complex multi-threaded WPF application for the financial sector, but I am also interested in cloud computing, web development, mobile development, etc.

Please visit my web site: www.ikriv.com.

Comments and Discussions

 
GeneralBravo Ivan !! Pin
Tacitonitus3-Apr-15 15:14
Tacitonitus3-Apr-15 15:14 
Thanks for posting this article/blog/comment/whatever Ivan..

I have a fairly large 64-bit app with one main UI thread, and one worker thread. They are both synchronized, and work exceedingly well together.

As the worker thread does its thing, it checks frequently to see if the UI thread wants it to do something. If it does, then the worker thread takes care of what the UI thread wants it to do. All fine and dandy, until a fatal error occurs.

When that happens, the worker thread calls MessageBox() to let the End User know what's going on, but lo and behold, it never returns from that call.. It hangs. Forever.

So I had no idea what was going on until I read your article. Thank you again. I checked other places on the Internet, and they all back you up. I don't actually care why the MessageBox() function doesn't work from within a Worker thread, I just consider it a fairly serious, yet hardly unprecedented, bug in the Windows API. And, of course, Microsoft will never acknowledge it, because they're so busy sticking their thumbs up their own.. but I digress..

Kudos for pointing out this huge bug in the Windows API.

So now I'm busy coding as simple a workaround as I can, which is: the worker thread posts a message to the UI thread's LastActivePopup() to issue the MessageBox() call for it, then waits on a synchronization variable until the UI thread sets it (the synchronization variable) to indicate that the MessageBox has finished processing.. Then the worker thread cleanly shuts the app down..

Of course, this means that every window in the entire app has to check for this particular (internal) message, which is a pain, but what're ya gonna do?

Anyway, kudos again on posting this..
GeneralMy vote of 1 Pin
.:floyd:.22-Feb-14 11:30
.:floyd:.22-Feb-14 11:30 
QuestionConvert UI thread back Pin
robiwano21-Feb-14 5:06
robiwano21-Feb-14 5:06 
AnswerRe: Convert UI thread back Pin
Ivan Krivyakov21-Feb-14 10:27
Ivan Krivyakov21-Feb-14 10:27 
QuestionLeaves a lot of questions open Pin
3soft22-May-13 22:25
3soft22-May-13 22:25 
AnswerRe: Leaves a lot of questions open Pin
Ivan Krivyakov23-May-13 8:06
Ivan Krivyakov23-May-13 8:06 
GeneralModal and not modal message boxes Pin
Stefan_Lang2-Nov-10 1:36
Stefan_Lang2-Nov-10 1:36 
GeneralGood stuff Pin
Manish K. Agarwal27-Oct-10 3:15
Manish K. Agarwal27-Oct-10 3:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.