Build your own CAB #12 – Rein in runaway events with the "Latch"

Wow, an even dozen, and I’ve still got a ways to go.  Just to prove that I can write a short post, this one is brief (because it was meant to be a little section in the Event Aggregator post). 

A couple people have asked for a PDF of the series when it’s done.  I’ll do my best to stitch it together and just slap it up on CodeBetter somewhere.  In the meantime, here’s the predecessor posts in the series:

 

  1. Preamble
  2. The Humble Dialog Box
  3. Supervising Controller
  4. Passive View
  5. Presentation Model
  6. View to Presenter Communication
  7. Answering some questions
  8. What’s the Model?
  9. Assigning Responsibilities in a Model View Presenter Architecture
  10. Domain Centric Validation with the Notification Pattern
  11. Unit Testing the UI with NUnitForms
  12. Event Aggregator
  13. Rein in runaway events with the “Latch” (This post)
  14. Embedded Controllers – Forthcoming
  15. MicroControllers – Forthcoming
  16. Subcutaneous Testing – Forthcoming
  17. Creating the Application Shell – probably a couple posts
  18. Wiring the Components with an IoC tool – Forthcoming

The “Latch”

In the last post I talked a little bit about runaway events in a fat client.  One event causes an action that changes another control which conceivably fires another event which eventually sends you application spiraling out of control.  All because a little bug went Kachhhoooooo!  What we need to do is ignore or turn off an event handler while a certain action is taking place.  You could just temporarily detach the event handler while you’re performing that action like this code:

 

            // Remove the event handler for the moment

            _someComboBox.SelectedIndexChanged -= new System.EventHandler(someHandler);

 

            // do something that would probably make _someComboBox fire the SelectedIndexChanged event

 

            // Put the event handler back

            _someComboBox.SelectedIndexChanged += new System.EventHandler(someHandler);

 

It works, but I wouldn’t want to do it everywhere.  It’s tightly coupling the code inside this method with the rest of the View.  I would bet that this approach would quickly make a View very difficult to modify. 

My preferred approach is what I call a “Latch” (it’s taken from a pattern used in messaging to stop a message from endlessly cycling between two systems that publish events to each other).  Inside any method or logical operation that could cause cascading events you simply set the latch to mark an operation in progress.  In the relevant event handlers you first check to see if the latch is set, and cancel any additional actions in the event handler is the latch is indeed set.  It could be as simple as just tracking a Boolean field in a View class.  Slightly more sophisticated is something like the “Latch” class from StoryTeller:

 

    public delegate void VoidHandler();

 

    public class Latch

    {

        private int _count = 0;

 

        public void Increment()

        {

            _count++;

        }

 

        public void Decrement()

        {

            _count–;

        }

 

        public bool IsLatched

        {

            get { return _count > 0; }

        }

 

        public void RunInsideLatch(VoidHandler handler)

        {

            Increment();

            handler();

            Decrement();

        }

 

        public void RunLatchedOperation(VoidHandler handler)

        {

            if (IsLatched)

            {

                return;

            }

 

            handler();

        }

There isn’t too much to the usage.  In the method that performs work you might do this:

 

            _latch.RunInsideLatch(delegate

                                      {

                                          // The actions that spawn cascading events

                                          activatePresenter(presenter, page);

 

                                          _tabControl.Items.Add(page);

                                          _tabControl.SelectedTab = page;

                                      }

                );

In an event handler effected by this work you could guard the event propagation by doing this

 

        void TabControl_TabSelected(object sender, TabEventArgs args)

        {

            if (_latch.IsLatched)

            {

                return;

            }

 

            ContentTab tab = (ContentTab) TabControl.SelectedTab;

            activatePresenter(tab.Presenter, tab);

        }

or this version (fun with anonymous delegates):

 

        void TabControl_TabSelected(object sender, TabEventArgs args)

        {

            _latch.RunLatchedOperation(

                delegate

                    {

                        ContentTab tab = (ContentTab)TabControl.SelectedTab;

                        activatePresenter(tab.Presenter, tab);                       

                    });

        }

I’ve used this pattern about 3-4 times with some success.  It’s especially powerful in conjunction with an Event Aggregator.

So what did I really buy here?  In the application, opening a new screen involves the creation and activation of a new TabControl, which raises an event for selecting a new tab.  For tabs that are just inactive, I need an indication from the SelectedTab event of a TabControl to tell that particular Presenter to reactivate.  The SelectedTab event is necessary for screens that are already open, but nothing but trouble for creating a brand new Tab.  By setting a latch in the event that opens a new TabControl, I an easily ignore the SelectedTabl event just while the TabControl is being setup.

Is this really a design pattern?

I’ve used some derivation of this solution on at least four projects, so it’s safe to say that it is *a* pattern.  Design patterns generally aren’t anything terribly fancy, there just things that you do – repeatedly.  When experienced people learn design patterns I often hear some snorting to the effect of “I already do this.”  Yes, that’s kind of the point in calling it a “pattern.” 

I’m not an officially sanctioned pattern naming body, so it’s not necessarily appropriate for me to be making up the name here.  I’d bet anything that someone else has already described this pattern and I’m just not familiar with the named pattern.  If you’ve seen this written up somewhere else, please throw in a link in the comments.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Build your own CAB, Design Patterns. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://enumeratethis.com James Miles

    This can be handled quite nicely in Rx…

    http://enumeratethis.com/2010/08/27/latch-design-pattern-in-rx/

    I’ve blogged about it.

  • http://www.minddriven.de Matthias

    Nice little pattern! Everytime since my first UI application I stumbled over this problem. Usually I used boolean flags to solve this problem, but often there had come the time where a View contained more and more boolean flags and the general view got lost. Boolean flags are a mess to solve that, the Latch is not. It’s a great and explicit way to solve the issue. Thanks for that!

    Cheers, Matthias

  • ZeusTheTrueGod

    Hi
    I worked some times with same problem, for example two linked combobox(when you select something in one, second should select the same)
    I prefer this model:
    Each event test some field(same as IsLatched). When someone choose a value in combobox, the controller method is invoked, then presentation model is changed and method view.RefreshData is called inside RunLatchedDelegation.
    In real application i have hierarchy of view and controllers,
    so each parent controller can intercept any action of child controller, that allows user actions on one view to be visible on others

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    Doh! Nice catch Mark.

  • http://codeliability.blogspot.com Mark Lindell

    One other improvement: If an exception occurs during the delegate would want the latch to handle the decrement.

    public void RunInsideLatch(VoidHandler handler)
    {
    Increment();
    try
    {
    handler();
    }
    finally
    {
    Decrement();
    }
    }

  • Simon Jones

    Great series. Can you let me know if you intend to cover best practices for form flow. There is probably a better term for this, but what I mean is the logic for deciding which forms to display and in what order.

  • http://consultutah.com/weblog.aspx Jeff Lewis

    One suggestion would be to make Latch implement IDispose. The constructor would Increment and the Dispose method would Decrement. This would help ensure that they always get called in pairs:

    using (new Latch())
    {
    ContentTab tab = (ContentTab)TabControl.SelectedTab;
    activatePresenter(tab.Presenter, tab);
    }

  • Ollie

    Is this not just an implementation of a non blocking synchronisation mechanism at a event handler level?

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    Martin,

    That’s cool. Thanks for the tip.

    Jeremy

  • http://community.ative.dk/blogs/ Martin Jul

    Another interesting event handling pattern that I have used is a transacted event mechanism.

    Assume that you have a graph of objects where each node has an ObjectUpdated-event. Observers subscribe to these events to display the graph.

    Now, when the graph is being updated we encounter a number of problems – every time we update something in the graph we trigger the Observers possibly triggering yet more events. Also, if the same node is updated by more than one operation during the graph update the Observers get invoked multiple times for the same object, and finally, the real issue is if the update operation is not atomic the graph is in an invalid state while the events are being raise.

    Enter the transacted event latch.

    We implemented this by basically using a latch-like approach to collect all the events that wanted to fire during the transaction in a transaction object, then when the transaction was completed, firing the queued up events (after eliminating duplicates to improve performance).

  • http://www.ayende.com/Blog/ Ayende Rahien

    skware,
    Not really. If you need to do explicit thread management, you have already lost. It is usually best left to the framework to coordinate that.

  • skware

    It might be worth pointing out that most of that code is non threadsafe and in production would need to be made so.

  • http://www.evanhoff.com/ Evan

    This series of posts is *really good* stuff.. Thanks for taking the time to share.. ;-)