The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My work

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,329 other followers

Windows Message Loop and Application Reentrancy

Posted by jpluimers on 2013/05/21

One of the things you must be careful with is reentrancy in your application through a message loop.

The most obvious way is Application.ProcessMessages: it will loop until all messages from the Windows message queue are processed, whether your application is ready for them or not.

A less obvious way is because of modal dialogs or forms. They have their own message loop which might cause global reentrancy in your application (for instance through TTimer objects).

That was the case for this problem: stack overflow with repeated DispatchMessageW in the call stack.

A couple of ways to try to avoid these issues:

  • Don’t cause a secondary message loop.
    You can refrain from calling Application.ProcessMessages, but you cannot always avoid modal dialogs.
  • Protect each of your event handlers by disabling the path to it as soon as it gets called.
    This means disabling the Enabled property for instance of TTimer, TControl, TAction, or other objects that cause events.

–jeroen

via: windows – stack overflow with repeated DispatchMessageW in the call stack – Stack Overflow.

7 Responses to “Windows Message Loop and Application Reentrancy”

  1. Anonymous said

    What about avoid reentrancy on WMCopyData?

    I mean, some (two, …, five or more) EXEs do call SendMessage to my Form Handle, i need to process them in order, not loose any.

    The main problem is that my processing time for each one is huge (minutes, hours, days, …) and do a lot of GUI updates that must be shown on Window, asks user for data and actions, etc. Threads are imposible (too much code and user must interact in middle, threads and GUI update is a really pain to control).

    Workflow to better understand:

    While my application is on middle of work, any other app can send a message to my app to tell it must do something as soon as it can… and that can be asked by more than one application (different EXE, i have no code control on it).

    The problem: My procedure WMCopyData is called while inside a for in any other part of the app.

    I though on a solution… (it does not work, latter i will explain why) … store on a list that pending actions recieved.

    Problem: Caller must stay freeze while sent message is not fully processed (not just only recived), it must stay freeze until my application does the job, that can be days (normally just a few seconds or minutes), and while in middle of such processing the user must interact with that process.

    An example would be better understand:

    App A (mine) stays with a Window shown and user responsive (user can use its menu, etc), and also stays listening to SendMessage from other apps.
    While App A is running it can recieve multiple SendMessage from different apps (closed code on them, no source code).
    If Only App B SendMessage to App A, App B stays freeze until App A do its job for that message sent.
    But if while App A is processing the message of App B, it recieves a message from App C, happns the horror.

    App A re-enter on WMCopyData and all sort of bad things happens.

    I had tried to put a flag, so i can know if i am on middle of a processing, so i can ignore all the rest messages… but that looses them and other Apps continue running, they not stay waiting for my app to end processing.

    I had tried to store such messages on a TMyList… but that causes the other Apps to continue (they not stay waiting).

    If WMCopyData ends, the app that do the SendMessage, continues, so i must not let WMCopyData to end till i do what i need to do for such Message.

    But here comes the ugliest part… if i do whatever i do to stay inside WMCopyData (like a loop), my App freezes.

    And there is no solution to my problem yet.

    Lets see a trace:

    App A (mine) is running… with a window shown… user can interact with that window
    While that is happening, any other App can SendMessage to App A
    App A start processing such ‘order’ and its action may involve user interaction… i need to not process any other till that one ends.
    App A… while on middle of such process (that can be in a waiting state for user interaction)… reenters WMCopyData (the procedure that responds to recieving messages) because Apps B, C, D, …, Z, AA, AB, …, ZZ, AAA,… has sent one (each app can send only one because they are suposed to stay freeze until i end procesiing its message, they need to know when i have finished to continue doing their jobs)… and that is exactly want i want to avoid, reenter on WMCopyData, how can i cause it to differ till i am ready to process another one?

    I do not get any way that avoids WMCopyData been called while my app is procesing a previous call to WMCopyData.

    Think on this: One of such processing may involve asking the user (aka, human) to enter a name, number, path where to open/save, etc., and i need to HOLD the rest of such messages till that ‘order’ is really ended.

    Worst: Some part of the processing depends on Timers (very complex processing).

    In short words (with only one message sent): App A recieve message for Order A from App B, App B freezes, App A procedure WMCopyData starts, a long interactive process is run (human must act in middle of it, etc), it finally ends, so WMCopyData procedure finally reaches its last line, then App B continues running.

    I need to cause a HOLD on such recieve, so the rest stay pending to be recieved… like closing a door in fron of a line of persons, only one person at a time, please, the rest stay there waiting till your turn reaches.

    I can not touch code of other Apps, only on mine… my App actions, depending on message recieved must do a really complex tasks, and data recieved is also very complex and depends a lot on what tasks is demanded, some also involves user/human interaction, many forms, modal ones included, etc.

    As i said, changing all GUI human interaction to a Safe Threaded is impossible in less than a million years.

    As soon as WMCopyData procedure ends, the sender continue running.

    If i do a live pooling, live loop (also tested letting CPU go to 100%) inside WMCopyData checking Boolean value to continue, it freezes my whole App in a Live Lock, loop does never end.

    Is really so complex to put a HOLD concept on such that prodecure?

    • jpluimers said

      Rephrase your question in a shorter way, then post it to stack overflow as this really is about a generic problem of developing applications running on Windows that need to queue some work, then wait for it to be completed while the queued items are being processed in order.

    • CRConrad said

      First thing that comes to mind is, for each incoming message to handle from another app, your app should launch another instance (invisible, windowless) of itself to handle that message.

  2. delphiuser2349-1 said

    is’nt there for modal dialogs the release
    (FormModalDialog.release) – method ?

  3. Jan Doggen said

    weather -> whether ;-)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: