When Events Go Bad

Yesterday, I discovered the dark, evil, brooding side to using lambdas to hook up events, even though they look so cool. Here’s an example:

public void GetCustomerOrders(string storeId)
{
    Proxy.DocumentDownloadCompleted += (data) => this.HandleCustomerOrders(data);
    Proxy.GetXML("customerorderservice.svc/customerorders/" + storeId);
}

All well and good, that works like a champ. Usually. As long as you don’t want to ever unhook the event.

But let’s say you want to do something like this when the response comes back.

private void HandleCustomerOrders(Stream data)
{
    base.Proxy.DocumentDownloadCompleted -= this.HandleCustomerOrders;

    // Do something interesting here.
}

Maybe you want to do this because you have multiple handlers hooked up to the same event and in reality, you only want to handle one at a time. The problem here is that the unhooking does nothing here because that HandleCustomerOrders isn’t actually the function handling the event. When the compiler finds a lambda, it does one of two things. If there are variables that the lambda closes around, the compiler creates an anonymous private class on the enclosing class. If there aren’t any variables to close around, the compiler creates a new anonymous function on the current class. In either case, the event you think you are hooking up to is actually being hooked up to the created anonymous function. When you try to unhook, nothing happens because it was never hooked up to begin with.

In cases where you want to have the ability to unhook from events, you can’t use lambdas to hook up your events. You have to be a bit more old school, if less hip and do this.

public void GetCustomerOrders(string storeId)
{
    base.Proxy.DocumentDownloadCompleted += this.HandleCustomerOrders;
    base.Proxy.GetXML("customerorderservice.svc/customerorders/1");
}

By doing that, you will be able to unhook the events when the response happens. This public service announcement brought to you by the lost 2 hours of my dumbfounded life yesterday afternoon.

Leave a Reply

Your email address will not be published. Required fields are marked *