Jeremy D. Miller -- The Shade Tree Developer

Sponsors

The Lounge

Syndication

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
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.


Posted Mon, Jul 2 2007 6:29 PM by Jeremy D. Miller

[Advertisement]

Comments

Evan wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Mon, Jul 2 2007 8:50 PM

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

skware wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Tue, Jul 3 2007 9:49 AM

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

Ayende Rahien wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Tue, Jul 3 2007 10:48 AM

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.

Martin Jul wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Tue, Jul 3 2007 2:14 PM

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).

Jeremy D. Miller wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Tue, Jul 3 2007 4:07 PM

Martin,

That's cool.  Thanks for the tip.

Jeremy

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB #13 - Embedded Controllers with a Dash of DSL
on Fri, Jul 6 2007 12:40 PM

Just to continue the world's longest run on sentence. Before I start, here's the table of contents

Sam Gentile wrote New and Notable 177
on Wed, Jul 11 2007 8:16 AM

Multithreading and Concurrency Software Transactional Memory Part IV - Thread-Bound Transactions Software

Insane World wrote The
on Wed, Jul 11 2007 10:16 AM

The

Ollie wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Thu, Jul 12 2007 5:10 AM

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

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB #14: Managing Menu State with MicroController's, Command's, a Layer SuperType, some StructureMap Pixie Dust, and a Dollop of Fluent Interface
on Tue, Jul 24 2007 5:18 AM

The title is a mouthful and accurately implies an alarmingly high jargon to code ration, but I just didn't

Jeff Lewis wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Tue, Jul 24 2007 10:16 AM

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);    

}

Jeremy D. Miller -- The Shade Tree Developer wrote The Build Your Own CAB Series Table of Contents
on Wed, Jul 25 2007 9:22 PM

Yes, this is overdue. Here is an introduction and table of contents to my "Build Your Own CAB"

Simon Jones wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Thu, Jul 26 2007 10:45 AM

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.

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB #14: Managing Menu State with MicroController's, Command's, a Layer SuperType, some StructureMap Pixie Dust, and a Dollop of Fluent Interface
on Thu, Jul 26 2007 10:57 AM

The title is a mouthful and accurately implies an alarmingly high jargon to code ration, but I just didn't

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB #15 - MicroControllers
on Sun, Oct 21 2007 9:13 PM

After a bit of a hiatus and a fair amount of pestering, I'm back and ready to continue the "Build

Mark Lindell wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Wed, Nov 7 2007 10:12 AM

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();

           }

       }

Jeremy D. Miller wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Wed, Nov 7 2007 10:14 AM

Doh!  Nice catch Mark.

Jeremy D. Miller -- The Shade Tree Developer wrote Resources from my DevTeach talks
on Thu, Nov 29 2007 12:03 PM

To everybody that attended one of my talks at DevTeach this week. All of the materials are now online

ZeusTheTrueGod wrote re: Build your own CAB #12 - Rein in runaway events with the "Latch"
on Sun, Jul 6 2008 12:56 AM

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

Sam Gentile's Blog wrote New and Notable 177
on Tue, Dec 2 2008 8:38 PM

Multithreading and Concurrency Software Transactional Memory Part IV - Thread-Bound Transactions Software Transactional Memory Part V - Integration with System.Transactions Parallel LINQ Restating the Concurrency Problem Herb Sutter is starting a new

new ThoughtStream("Derick Bailey"); wrote Understanding The Application Controller Through Object Messaging Patterns
on Tue, Dec 22 2009 10:06 PM

Earlier in the year, I posted a few times on the Application Controller pattern that I was implementing

Add a Comment

(required)  
(optional)
(required)  
Remember Me?