Click here to Skip to main content
13,550,825 members
Click here to Skip to main content
Add your own
alternative version


102 bookmarked
Posted 21 Feb 2004
Licenced CPOL

An Event Pool

, 21 Feb 2004
Rate this:
Please Sign up or sign in to vote.
An event pool helps manage large amounts of events that otherwise clutter up your code and make maintenance difficult.

For a .NET 2.0 version, see Pete O'Hanlon's article.


The EventPool is part of the Model-View-Controller (MVC) technology roadmap series, which includes:

  • EventPool (this article)
  • IMemento (tbd)
  • UndoBuffer (tbd)
  • StateManager (tbd)
  • XmlGuiGenerator
  • Form2Xml (tbd)


Event pools are useful for managing large sets of events that you may typically encounter when working with an MVC model. A rich model often often contains many properties and undergoes many different state changes. Declaring a unique event (and sometimes a delegate with a subclassed EventArgs parameter) is time consuming and adds to the maintenance of the model.

The drawback to this approach is that subclassed EventArgs, while supported, must be cast to the correct subclass in the event handler. This moves the detection of incorrectly constructed event handlers from compile time to run time.

The Problem

Take a simple model, such as a four register stack used by a simple RPN calculator:

protected string[] registerStack={"0.00", "0.00", "0.00", "0.00"};

What we'd like to do is to provide an event that is fired whenever one of the register values changes so that any associated views can update the user interface, ex:

Let's say that the model represents the events with four properties:

  • X
  • Y
  • R3
  • R4

Typically, we would construct a delegate for the event signature:

public delegate void RegisterChangeDelegate(object sender, EventArgs args);

and our four events:

public event RegisterChangeDelegate RegisterXChangeEvent;
public event RegisterChangeDelegate RegisterYChangeEvent;
public event RegisterChangeDelegate RegisterR3ChangeEvent;
public event RegisterChangeDelegate RegisterR4ChangeEvent;

and invoke our events in the property setters. For example, the X register setter:

public string X
  get {return registerStack[0];}
    if (RegisterXChangeEvent != null)
      RegisterXChangeEvent(this, EventArgs.Empty);

The view informs the model of it's interest in change event using:

model.RegisterXChangeEvent+=new EventHandler(RegisterXChangeEventHandler);

This will allow our views of the model to wire up event handlers that are invoked when the model changes, and all is happy with world. There are three problems:

  • We've created event definitions that are a maintenance liability (albeit a small one in this example).
  • Unless the programmer is very good, he/she will forget to instrument the event, as I have done here.
  • We have to remember to always check if the event handler has actually been assigned.

The last problem can be worked around with some defensive event publishing, courtesy of Juval Lowy's and Eric Gunnerson's C# Best Practices Power Point presentation, downloadable here:

public class EventsHelper
   public static void Fire(Delegate del,params object[] args)
      if(del == null)
      Delegate[] delegates = del.GetInvocationList();
      foreach(Delegate sink in delegates)

This eliminates the "if" block and ensures that, even if the event isn't assigned, the setter will still work. For example, this is how the new "X" setter would appear:

public string X
  get {return registerStack[0];}

Much cleaner, but it still doesn't address the other two problems--lots of events and lack of instrumentation.

The Solution

The solution is an event pool. The event pool simplifies the management of many different delegates and their associated events and event handlers. Events are abstracted by associating the event handler with a tag. Events are invoked by referring to the tag (rather than the event delegate). The event pool also lends itself well to instrumentation so that the programmer doesn't have to remember to do this.

Given the above example, when we use an event pool, the following code is eliminated:

public delegate void RegisterChangeDelegate(object sender, EventArgs args);
public event RegisterChangeDelegate RegisterXChangeEvent;
public event RegisterChangeDelegate RegisterYChangeEvent;
public event RegisterChangeDelegate RegisterR3ChangeEvent;
public event RegisterChangeDelegate RegisterR4ChangeEvent;

The model fires any assigned events via the tag mechanism. For example:

public string X
  get {return registerStack[0];}

The view expresses its interest in the model's event in a slightly different manner:

model.EventPool.Subscribe("X",new EventHandler(RegisterXChangeEventHandler));

Loose Coupling

The danger, of course, is that the events to which you can subscribe are now very loosely associated with the events that published. How do you know if you are subscribing to an event that is still being published?

The answer is to tell the event pool what events you are publishing, via the Publish method:

virtual public void Publish(params object[] tags)
  foreach(object tag in tags)
    eventTagToDelegateMap.Add(tag, null);

The model, for example, publishes the events that it fires:

eventPool.Publish("X", "Y", "R3", "R4", "EntryStateChanged");

Now, when the view subscribes to the model's events, the event pool will verify that the event has been published and emit a warning if not (or you can change the code and have it throw an exception). The Subscribe method is overloaded so that a subscriber can optionally disable this checking, in the event (hahaha) that the publisher hasn't registered the events yet or is doing some dynamic event publication.

The Demonstration

The download includes an RPN calculator as a demonstration for the EventPool class. This demo a very clean MVC model and has a lot of events flying around, which are managed by the EventPool.


Documentation for the EventPool can be found on my website. This documentation will be extended to include the other technologies in the MVC model as the additional articles in this series are published.

The only interesting thing about the EventPool is the Subscribe method, which builds a multicast delegate:

virtual public void Subscribe(
     object tag,
     EventHandler eventHandler,
     bool loose)
  // do we verify that the handler exists?
  if (!loose)
    if (!eventTagToDelegateMap.Contains(tag))
      Trace.WriteLine("Event Pool does not contain an entry for: "+

  // create the delegate for this event handler
  MulticastDelegate newDelegate=new MulticastDelegate(eventHandler);

  // if this is a new tag...
  if (!eventTagToDelegateMap.Contains(tag))
    // ...add a new tag to the map.
    eventTagToDelegateMap.Add(tag, newDelegate);
    // ...otherwise, combine the new delegate with the delegates for
    // existing mapping.
    MulticastDelegate dlgt=(MulticastDelegate)eventTagToDelegateMap[tag];

    // if the tag has associated delegates already...
    if (dlgt != null)
      // ... combine the new delegate with the existing ones.
      dlgt=(MulticastDelegate)Delegate.Combine(dlgt, newDelegate);
      // delegates are data structures, which are therefore passed by value.
      // ... otherwise just assign the new delegate.


I personally find this approach more maintainable and easier to use when working with MVC models that publish many events.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Marc Clifton
United States United States
Marc is the creator of two open source projects, MyXaml, a declarative (XML) instantiation engine and the Advanced Unit Testing framework, and Interacx, a commercial n-tier RAD application suite.  Visit his website,, where you will find many of his articles and his blog.

Marc lives in Philmont, NY.

You may also be interested in...

Comments and Discussions

Generalnon of your posts was running !!! Pin
warrior_1121-Mar-09 9:40
memberwarrior_1121-Mar-09 9:40 
GeneralEnum instead of string Pin
philippe dykmans14-Sep-07 6:02
memberphilippe dykmans14-Sep-07 6:02 
GeneralRe: Enum instead of string Pin
Marc Clifton14-Sep-07 6:20
protectorMarc Clifton14-Sep-07 6:20 
GeneralRe: Enum instead of string Pin
philippe dykmans25-Oct-07 4:54
memberphilippe dykmans25-Oct-07 4:54 
GeneralThanks Pin
Pete O'Hanlon30-Mar-07 1:00
memberPete O'Hanlon30-Mar-07 1:00 
GeneralRe: Thanks Pin
Marc Clifton30-Mar-07 3:39
protectorMarc Clifton30-Mar-07 3:39 
GeneralC# 2005 EventHandlerList Pin
tjochum9-Sep-06 6:16
membertjochum9-Sep-06 6:16 
GeneralRe: C# 2005 EventHandlerList Pin
pashaper4-Dec-06 0:42
memberpashaper4-Dec-06 0:42 
QuestionUnsubscribe Pin
tjochum8-Sep-06 18:46
membertjochum8-Sep-06 18:46 
AnswerRe: Unsubscribe Pin
GavinMDodd28-Jul-08 23:11
memberGavinMDodd28-Jul-08 23:11 
General.NET 2.0 FYI Pin
mihamrah20-Jun-06 15:45
membermihamrah20-Jun-06 15:45 
GeneralRe: .NET 2.0 FYI Pin
CProgerTim21-Nov-06 10:06
memberCProgerTim21-Nov-06 10:06 
GeneralHiding defects Pin
tonyt3-Jul-05 10:02
susstonyt3-Jul-05 10:02 
GeneralPerformance Pin
foz7717-Feb-05 20:51
memberfoz7717-Feb-05 20:51 
GeneralDOT NET 2 BETA Pin
Robert M. Bouwens22-Jan-05 0:22
memberRobert M. Bouwens22-Jan-05 0:22 
GeneralDebugger is not stopping Pin
Johannes Oehl10-Nov-04 22:27
memberJohannes Oehl10-Nov-04 22:27 
GeneralDocumentability Pin
Dirk Rombauts6-Oct-04 12:37
memberDirk Rombauts6-Oct-04 12:37 
GeneralRe: Documentability Pin
Marc Clifton6-Oct-04 14:21
protectorMarc Clifton6-Oct-04 14:21 
GeneralRe: Documentability Pin
Dirk Rombauts7-Oct-04 7:11
memberDirk Rombauts7-Oct-04 7:11 
GeneralRe: Documentability Pin
Dirk Rombauts4-Oct-05 20:18
memberDirk Rombauts4-Oct-05 20:18 
GeneralGreat!!! Pin
Robert.Casas20-Aug-04 1:17
memberRobert.Casas20-Aug-04 1:17 
Generalprb: type converting & parsing Pin
Mehdi Gholam29-May-04 22:04
memberMehdi Gholam29-May-04 22:04 
QuestionReinventing? Pin
Daniel Turini12-Mar-04 9:32
memberDaniel Turini12-Mar-04 9:32 
AnswerRe: Reinventing? Pin
Marc Clifton12-Mar-04 9:43
editorMarc Clifton12-Mar-04 9:43 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.180515.1 | Last Updated 22 Feb 2004
Article Copyright 2004 by Marc Clifton
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid