events

Avoiding Events, or how to wrap an Event with a continuation handle

If there is one language feature of .NET that I've become increasingly apprehensive of it is events. On the surface they seem incredibly useful, letting you observe behavior without the observed object having to know anything about the observer. But the way they are implemented has a number of problems that makes me avoid them whenever possible.

Memory Leaks

The biggest pitfall with events is that they are a common source of "memory leaks". Yes, a managed language can leak memory — it happens anytime you create an object that is still referenced by an active object and cannot be garbage collected. The nasty bit that usually goes unmentioned is that an event subscription represents an object holding a reference to the observed instance. Not only does this go unmentioned, but Microsoft spent years showing off code samples and doing drag and drop demos of subscribing to events without stressing that you need to also unsubscribe from them again.

Every "memory leak" I've ever dealt with in .NET traced back to some subscription that wasn't released. And tracking this down in a large project is nasty work –taking and comparing memory shapshots to see what objects are sticking around, who subscribes to them and whether they should really still be subscribed. All because the observer affects the ability of the observed to go out of scope, which seems like a violation of the Observer pattern.

Alternatives to Events

Weak Event Pattern

A pattern I've implemented from scratch several times (the side-effect of implementing core features in proprietary code) is the Weak Event pattern, i.e. an event that uses a weak reference as the subscription, so that the observed class isn't pinned in memory by a subscriber.

.NET 4 Microsoft has even formalized this with the WeakEventManager to implement the Weak Event Pattern, although I prefer just overriding the add and remove on an event and using weak references under the hood. While this changes the expected behavior of events and is unexpected in public facing APIs, I consider it the way events should have been implemented in the first place, and use it as default in my non-public facing code.

IObservable

A better way of implementing the Observer pattern is IObservable from the Reactive Framework (Rx). Getting a stream of events pushed at you is a lot more natural for observation and allows for following a number of different behaviors in one observer. It also provides a mechanism for terminating the subscription from the observed end, as well a way deal with exceptions occuring in event generation. For new APIs this is definitely my prefered method of pushing state changes at listeners.

Using a continuation handle to subscribe to a single event invocation

A pattern I encounter frequently are one time events that simply signal a change in state, such as a connection being estatblished or closed. What I really want for these is a callback. I've added methods in the vein of AddConnectedCallback(Action callback), but always feel like their unintuitive constructs born out of my dislike of events, so generally I just end up creating events for these after all.

I could just use a lambda to subscribe to an event an capture the current scope much like the .WhenDone handler of Result, the lambda is anonymous making it impossible to unsubscribe:

xmpp.OnLogin += (sender,args) => {
  xmpp.Send("Hello");
  // but how do I unsubscribe now?
};

The mere fact that lambdas are being shown as convenient ways to subscribe to events without any mention about the reference leaks this introduces just further illustrates how broken both events and their guidance are. Using this closure, simplifies attaching behavior at invocation time and makes sure that unsubscribe is handled cleanly.

Doing a lot of asynchronous programming work with MindTouch DReAM's Result continuation handle (think TPL's Task, but available since .NET 2.0), I decided that being able to subscribe to an event with a result would be ideal. Inspired by Rx's Observable.FromEvent, I created EventClosure, which can be used like this:

EventClosure.Subscribe(h => xmpp.OnLogin += h, h => xmpp.OnLogin -= h)
  .WhenDone(r => xmpp.Send("Hello"));

Unfortunately, like Observable.FromEvent, you have to set up the subscribe and unsubscribe using an Action provided handler, since there isn't a way to pass xmpp.OnLogin as an argument and do it programatically. But at least now the subscribe and unsubscribe are handled in one place and I can concentrate on the logic I want executed at event invocation.

I could have implemented this same pattern using Task, but until async/await ships, Result still has the advantage, aside from continuation via .WhenDone or Blocking via .Block or .Wait, Result also gives me the ability to use a coroutine:

public IEnumerator<IYield> ConnectAndWelcome(Result<Xmpp> result) {
    var xmpp = CreateClient();
    var loginContinuation = EventClosure.Subscribe(h => xmpp.OnLogin += h, h => xmpp.OnLogin -= h);
    xmpp.Connect();
    yield return loginContinuation;
    xmpp.Send("hello");
    result.Return(xmpp);
}

This creates the client, starts the connection and suspends itself until connected, so it can then send a welcome message and return the connected client to its invokee. All this happens asynchronously! The implementation of EventClosure looks like this (and could easily be adapted to use Task instead of Result):

public static class EventClosure {
    public static Result Subscribe(
        Action<EventHandler> subscribe,
        Action<EventHandler> unsubscribe
    ) {
        return Subscribe(subscribe, unsubscribe, new Result());
    }

    public static Result Subscribe(
        Action<EventHandler> subscribe,
        Action<EventHandler> unsubscribe,
        Result result
    ) {
        var closure = new Closure(unsubscribe, result);
        subscribe(closure.Handler);
        return result;
    }

    public static Result<TEventArgs> Subscribe<TEventArgs>(
        Action<EventHandler<TEventArgs>> subscribe,
        Action<EventHandler<TEventArgs>> unsubscribe
    ) where TEventArgs : EventArgs {
        return Subscribe(subscribe, unsubscribe, new Result<TEventArgs>());
    }

    public static Result<TEventArgs> Subscribe<TEventArgs>(
        Action<EventHandler<TEventArgs>> subscribe,
        Action<EventHandler<TEventArgs>> unsubscribe,
        Result<TEventArgs> result
    ) where TEventArgs : EventArgs {
        var closure = new Closure<TEventArgs>(unsubscribe, result);
        subscribe(closure.Handler);
        return result;
    }

    private class Closure {
        private readonly Action<EventHandler> _unsubscribe;
        private readonly Result _result;

        public Closure(Action<EventHandler> unsubscribe, Result result) {
            _unsubscribe = unsubscribe;
            _result = result;
        }

        public void Handler(object sender, EventArgs eventArgs) {
            _unsubscribe(Handler);
            _result.Return();
        }
    }
    private class Closure<TEventArgs> where TEventArgs : EventArgs {
        private readonly Action<EventHandler<TEventArgs>> _unsubscribe;
        private readonly Result<TEventArgs> _result;

        public Closure(Action<EventHandler<TEventArgs>> unsubscribe, Result<TEventArgs> result) {
            _unsubscribe = unsubscribe;
            _result = result;
        }

        public void Handler(object sender, TEventArgs eventArgs) {
            _unsubscribe(Handler);
            _result.Return(eventArgs);
        }
    }
}

While this pattern is limited to single fire events, since Result can only be triggered once, it is a common enough pattern of event usage and one of the cleanest ways to receive that notification asynchronously.

By arne on | geek, mindtouch | 1 comment
Tags: , , , ,

Observable event subscription

The other day I was trying to create an explicit interface implementation of an event and ran into a snag. Now I’ve done many explicit interface implementations before, but, I guess, never of an event, because I’d not seen the below compiler error before:

An explicit interface implementation of an event must use property syntax

Huh? I did some searches on that error and the best reference was this page. I had long forgotten that the whole += and -= was closely related to how properties work. But instead of using get and set you can create your own logic for subscribe and unsubscribe using add and remove.

As Oliver points out on his blog, it does mean that your event just becomes a facade and you still need another event that actually is being subscribed to. So for that explicit interface implemenation you’d get something like this:

interface IFoo
{
   event EventHandler FooHappened;
}

class SomeClass : IFoo
{
  private event EventHandler internal_FooHappened;

  public event EventHandler IFoo.FooHappened
  {
    add { internal_FooHappened += value; }
    remove { internal_FooHappened -= value; }
  }

  private void OnFooHappened()
  {
    if( internal_FooHappened != null )
    {
      internal_FooHappened(this,EventArgs.Empty);
    }
  }
}

Now this is really an edge case, imho. But the same syntactic trick does allow for something else that’s pretty cool, i.e. being able to be notified when someone subscribes to your event. I’ve had it happen a number of times, where it would have been useful to take some action on subscription. Maybe the event needs some extra resource, that you don’t want to initialize unless someone needs it. It may even be that the real event handler is that resource. So now you can use the above syntax and put extra logic inside of the add to initialize that resource, like this:

class SomeClass
{
  SomeResource myResource;

  public event EventHandler FooHappened
  {
    add
    {
      if( myResource == null )
      {
         myResource = new SomeResource();
      }
      myResource.FooHappened += value;
    }
    remove
    {
      myResource.FooHappened -= value;
      if( myResource.FooHappened == null )
      {
         myResource.Dispose();
         myResource = null;
       }
    }
  }
}

Are delegates the reason we have C#?

This may be ancient news, but I just came across an article that strongly implied that the reason .NET came about was because Sun didn’t like Microsoft’s addition of delegates to J++. That surely is a condensation of events, but it’s certainly an interesting yarn.

I got into this whole subject because I needed an object to subscribe to the state change of another object in my java project. And I didn’t want to create a tight coupling between otherwise unrelated objects. In C#, I would have created an event for the state change and have the second object subscribe to it. Done.

Alas, I’m in java and don’t have delegates, e.g. no events in the way i’m used to. I remembered dealing with creating lots of anonymous inner classes during some long ago experiences with swing programming, which I always found to be less than transparent in presentation. So I figured I’d do some digging to see how delegation and events should be handled in java. I don’t like seeing getFoo()/setFoo() from someone not used to C# properties, and I don’t want to subject someone else to my C#-ing of java code in return.

I started googling java, delegates and inner classes and came across a plethora of interesting articles, including the obligatory C# is better better than java because it has delegates and java kicks C#’s ass because isn’t littered with atrocious syntactic sugar like delegates when inner classes will do variety. Of these, the most entertaining was a rather testy condemnation of delegates in J++ in the form of a white paper on Sun’s site. Considering the stance Sun has taken over the years on java, i.e. binding the language, runtime and philosophy into a single indivisible unit, having MS try subvert the language with what to many looks like a procedural programming throwback certainly could have been a significant motivator for the lawsuit that revoked Microsoft’s java license. Looking at C# and the CLR, Microsoft obviously saw a lot of things it liked in the java language and the jvm. So the result that .NET came about because Sun rejected delegates doesn’t seem too far fetched and my favorite version of the story so far.

Now, back to the problem at hand, how does one do delegation in java and the answer does appear to be with inner classes functioning as callbacks. This certainly does the trick. But that’s a bunch of code and interfaces to create which in the end doesn’t improve the readability of the code. As an illustration, here is the C# code and the java code I created to get the same effect. Note: I didn’t need the extra information that C# events provide, i.e. the event source and event arguments, so I left them out of the java version to keep the code more concise. I also didn’t do any checking if there are subscribers, etc — read: this is an illustration not production code :)

Publisher

// C# Publisher
public class Publisher
{
  // create the event, which implicitly gives us add/delete subscribers
  public event EventHandler someAction;

  public void DoAction()
  {
    Console.WriteLine("Start action");
    //implictly call all subscribers
    someAction(this, EventArgs.Empty);
    Console.WriteLine("End action");
  }
}
// java Publisher
public class Publisher {

    private List<EventHandler> subscribers = new ArrayList<EventHandler>();

    public void subscribeToAction(EventHandler notifier)
    {
        subscribers.add(notifier);
    }

    public void doAction()
    {
        System.out.println("Start action");
        for( EventHandler subscriber : subscribers ) {
            subscriber.handle(this);
        }
        System.out.println("End action");
    }
}

Subscriber

//C# Subscriber
public class Subscriber
{
  private string name;

  public Subscriber(string name)
  {
    this.name = name;
  }

  public void AttachToPublisher(Publisher publisher)
  {
    // subscribe to the event. This creates a closure for this particular
    // instance of Subscriber.
    publisher.someAction += new EventHandler(RespondToAction);
  }

  void RespondToAction(object sender, EventArgs e)
  {
    Console.WriteLine("Responding to action for '" + name + "'");
  }
}
// java Subscriber
public class Subscriber {

    private String name;

    public Subscriber(String name) {
        this.name = name;
    }

    public void attachToPublisher(Publisher publisher) {
        // create a new anonymouse instance of the EventHandler
        // as a closure for this instance of Subscriber
        publisher.subscribeToAction(new EventHandler() {
            public void handle(Publisher publisher) {
                respondToAction();
            }
        }
        );

    }

    private void respondToAction() {
        System.out.println("Responding to action for '" + name + "'");
    }
}

EventHandler

In C# this is just built in plumbing. In java we create a simple interface that our anonymous inner class will implement:

public interface EventHandler {
    void handle(Publisher publisher);
}

Now we exercise the code:

      Publisher p = new Publisher();
      Subscriber s1 = new Subscriber("abc");
      Subscriber s2 = new Subscriber("xyz");
      s1.AttachToPublisher(p);
      s2.AttachToPublisher(p);
      p.DoAction();

The java code is virtually identical just with different casing for code style and both produce this output:

Start action
Responding to action for 'abc'
Responding to action for 'xyz'
End action

Now add lost of different events and unsubscribing of events, plus more complex EventHandlers and the amount of code you end up writing quickly becomes significant. If there is one thing object oriented programming encourages us to do is to take repetitive code patterns and formulate reusable objects. Plenty of people in the java community have created delegate-like helpers that make delegation easier to read and maintain than simple inner classes, my favorite so far being Alex Winston’s strongly typed approach.

So are delegates just syntactic sugar or a throw-back to procedural coding? For those with only a cursory understanding of delegates, they do just look like function pointers, like C, or at best, type-safe function pointers. But just like inner classes they create instance specific closures, plus they throw in functionality for handling multi-casting and handling synchronous and asynchronous invocation of the closure. I, at least, think delegates as a first-class citizen of the runtime make life easier, improve readability and do not detract from the object oriented nature of the surrounding code.

By arne on | .net, geek | 1 comment
Tags: , , , , ,