Event performance optimization with the EventHandlerList

December 25, 2007 23:35 by MartinHN

When using custom events (event delegates) in your ASP.NET pages, user controls and server controls, many developers might define their Events as public fields, like this:

public event EventHandler<EventArgs> MyCustomEvent;


And use this code to fire the event:

protected void OnMyCustomEvent(EventArgs e)
{
  if(MyCustomEvent != null)
  {
    MyCustomEvent(this, e);
  }
}

 

Nothing is wrong with the approach of the latter, but defining the MyCustomEvent as a public field introduces two problems:

    1. Even though no clients have registered any delegates to the invocation list of your event, the compiler generates
      one private delegate field for each event delegate in your class. This is a waste of server memory, especially if
      you have several events inside your class.

    2. One Add and one Remove method is generated for each event field of your class. When clients use += and -= to add
      and remove delegates from the invocation lists of your class' events, these methods are called behind the scenes.
      These two compiler-generated methods are thread-safe, which means they include extra code to synchronize threads
      that are accessing these methods. This means, that everytime a client adds or removes a delegate to or from the
      invocation list of an event, they have to get a lock before they can do the actual work. This introduces an
      unnecessary overhead because most page developers don’t use multiple threads and therefore there is no need for
      thread synchronization.

     

    The EventHandlerList is the answer to our issues. This class comes with the .NET Framework. The EventHandlerList is a linked list of delegates,which is optimized for adding and removing delegates. To use the EventHandlerList in your classes, you need to add a private static key for each event your class exposes. The code bellow defines a key for MyCustomEvent:

    private static readonly object MyCustomEventKey = new object();

    The memory is allocated only once, because the key is static.

    After this, you need to define your events as properties - not fields. These event properties has a different syntax that normal get-set properties. Event properties uses add-remove instead of get-set. The following property, is an event property for MyCustomEvent:

    public event EventHandler<EventArgs> MyCustomEvent
    {
      add { Events.AddHandler(MyCustomEventKey, value); }
      remove { Events.RemoveHandler(MyCustomEventKey, value); }
    }
     

    Every Page, UserControl and WebControl - among others - has a protected property of type EventHandlerList named Events. With this approach, when clients use += to add a delegate to the invocation list of the MyCustomEvent, the add method of the event property calls the AddHandler method of the EventHanderList class, as the code above will tell you. As for -= the RemoveHandler method is called.

    The EventHandlerList class maintains a linked list which can have none or one entry for each event. The AddHandler method checks whether this internal linked list contains an entry for an event with the given event key. If it does, the method calls the Combine method of the Delegate class to add the client delegate to the invocation list of the event. If this internal list doesn’t contain an entry for an event with the given event key, the AddHandler method just adds a new entry.

    With this new approach, we need to update our OnMyCustomEvent Method, which is responsible for firing the event:

    protected void OnMyCustomEvent(EventArgs e)
    {
      EventHandler<EventArgs> handler = Events[MyCustomEventKey] as EventHandler<EventArgs>;
    
      if (handler != null)
        handler(this, e);
    }
     

    This method uses the MyCustomEventKey as an index in the Events list to access the MyCustomEvent-event. The Events list will return null if it does not contain an entry at the specified index. This will happen when no clients has subscribed to the MyCustomEvent.

    Using the EventHandlerList class automatically resolves the two previously mentioned performance problems with the event fields.

    Technorati Tags: ,

     

    kick it on DotNetKicks.com

    Currently rated 5.0 by 1 people

    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Add to: Facebook Add to: Digg Add to: Del.icio.us Add to: Reddit Add to: Furl Add to: Yahoo Add to: Spurl Add to: Google Add to: Technorati

    Comments

    February 22. 2008 22:25

    trackback

    Trackback from DotNetKicks.com

    Event performance optimization with the EventHandlerList

    DotNetKicks.com

    Add comment


    (Will show your Gravatar icon)  

      Country flag

    biuquote
    • Comment
    • Preview
    Loading



    Powered by BlogEngine.NET 1.4.0.0
    Theme by Mads Kristensen

    About the author

    Martin Høst Normark

    Senior Frontend Developer at TraceWorks.

    View Martin Høst Normark's profile on LinkedIn

    Recent comments

    Comment RSS

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in  anyway.

    © Copyright 2008