locked
How does Invoke execute during ShowDialog? RRS feed

  • Question

  • Hello!

    This is a bit of a specific question and I'd like to get some insight into what's going on behind the scenes, because the info I've managed to collect seems to explain this, but I'd like to get some clarification just to confirm my assumptions.

    So I'm using Windows Forms.

    I've got my main Form class (mainWindow) with a button that opens a dialog Form using ShowDialog(mainWindow). I also have a Thread running in mainWindow which periodically BeginInvokes a simple method in mainWindow that prints stuff in a TextBox belonging to mainWindow (since I created the TextBox in the main thread). So the thread BeginInvokes a method of the mainWindow class which in turn will modify the Text in the Textbox.

    I've read that Control::Invoke and Control::BeginInvoke are pretty much equivalent to SendMessage and PostMessage, in that they cause a message to be placed into the message queue of the window you send it to. SendMessage messages are prioritized. Here's a detailed article that I used for reference.

    Additionally, I have also read that a ShowDialog call prevents any code following it from executing until the dialog being shown gets its DialogResult value set.

    So, if both of these things are true, how come my textbox text is still being modified while I've got my dialog form open? I understand that there's more than meets the eye and I feel like the key to understanding it is somehow connected to this detail mentioned in the article with regards to SendMessage:

    "SendMessage, while blocking the current thread, continues to process messages that are sent to the message pump using SendMessage or one of the functions that send nonqueued messages. This means that your code must be prepared to handle incoming messages when blocked on a SendMessage call"

    It definitely looks like ShowDialog too is not "truly" blocking and it behaves in a similar fashion to how SendMessage is described here. It "blocks" any following code from executing by not returning, but ShowDialog itself keeps the message queue pumping in a somewhat... weirdly "recursive" sort of way? Which means any invokes from other threads are still processed. How is this achieved under the hood though?

    Thursday, October 22, 2020 6:38 PM

Answers

  • ShowDialog also disables the parent/owner window of the dialog. When a window is disabled it react to user input in a different way e.g. beep when you click. 

    There is one message queue per thread. There is no separate queue for individual windows. if you want to prioritize for individual windows you have to rewrite the message queue (call PeekMessage with a valid window handle, for example). 



    Visual C++ MVP

    • Marked as answer by kirillandy Wednesday, October 28, 2020 7:23 AM
    Friday, October 23, 2020 3:51 PM

All replies

  • SendMessge basically says "I will wait here until my order is processed", it does not mean you magically jump in front of the queue. Sure it is blocking you, but it doesn't mean people ahead of you won't get their orders before you do (except when you are sending non-queued messages).

    ShowDialog create another message pump, which basically says "I will accept order myself and everyone already waiting in line come to me". it still doesn't get your own orders prioritized because you outsourced the order processing to the same dealer that was used by the previous order collector. 

    non-queued messages are line jumpers, Those people call the dealer directly and get things done instead of having formal orders. 



    Visual C++ MVP


    Friday, October 23, 2020 2:56 AM
  • OK, so, essentially, even though ShowDialog stops my handler function that's calling it from completing until the dialog is closed, it also continues to manage the mainWindow queue (and all of its components, like TextBoxes, Buttons, etc. since those are "windows" as well) in addition to the queue of the dialog window?

    And consequently, I understand that, say, a button Click event for a button in the mainWindow will NOT cause any of my Click handler functions to run, but just trigger different (default?) behavior (an audio cue + dialog window "flashing") because there's a value somewhere in the mainWindow object that indicates a dialog window is open, and this changes the program flow?

    Friday, October 23, 2020 9:25 AM
  • Raymond Chen's blog has a series of articles discussing modality that you may find helpful.

    https://devblogs.microsoft.com/oldnewthing/?s=modality

    Friday, October 23, 2020 10:45 AM
  • Thank you, I'll definitely check them out!
    Friday, October 23, 2020 11:35 AM
  • ShowDialog also disables the parent/owner window of the dialog. When a window is disabled it react to user input in a different way e.g. beep when you click. 

    There is one message queue per thread. There is no separate queue for individual windows. if you want to prioritize for individual windows you have to rewrite the message queue (call PeekMessage with a valid window handle, for example). 



    Visual C++ MVP

    • Marked as answer by kirillandy Wednesday, October 28, 2020 7:23 AM
    Friday, October 23, 2020 3:51 PM
  • Alright, great, so I was close in 1 of the 2 cases :D. The messages to the windows are placed in the general queue and are still processed but they cause different behavior when the window is disabled/"blocked" by a modal window it owns.

    A message comes with a window handle which determines what window it refers to.

    Thank you Jiang and... um... RLWA32 for the help!

    Wednesday, October 28, 2020 7:22 AM