PRISM event aggregator: more leaky than it seems

Gotcha of the day: the Prism framework for WPF and Silverlight offers an application-wide event bus system that allows you to publish and subscribe events without having to have a reference to the publisher. This is hugely useful for decoupling parts of an application that should not hold references on one each other just because you want to be notified that something is going on.

By default, when you subscribe to an event, you pass only a WeakReference of yourself (that’s you, the subscriber object); the subscriber will still be garbage-collected when it becomes unreachable. There is however an option to keep the subscriber alive as long as it does not explicitly detach itself from the event subscription. This behavior is useful when listening to the event is the sole purpose of something. Per documentation, the weak reference is the default. What actually happens however is that you get the second behavior, and instances of the subscriber classes leak out into the application. Which is not a huge problem until you dynamically create and abandon these. Which is what I do.

However, there is a bug in the CompositePresentationEvent class. In the Subscribe method, there is a fork whether a filter predicate has been set or not; in the branch where no filter is set, the keepSubscriberReferenceAlive parameter (which controls if the subscriber is kept alive by the subscription) is not applied correctly. Here’s the culprit:

if (filter != null)
{
  filterReference = new DelegateReference(filter, keepSubscriberReferenceAlive);
}
else
{
  filterReference = new DelegateReference(new Predicate<TPayload>(delegate { return true; }), true);
}

See the “true”? Yep. Should be “keepSubscriberReferenceAlive”.

The problem is described in PRISM’s defect tracking; since it’s low priority, it seems unlikely it’s going to be fixed. So you can either correct and compile your own version, or use the overload of the method that allows you to specify a filter. What I had to find out is that you cannot use an anonymous method in the form of a lambda expression like “(filter) => true” as a filter: since this is a private method behind the scenes, you get a MethodAccessException. You need to specify a non-anonymous method.

EventAggregator.GetEvent<MyEvent>().Subscribe(MyHandler, ThreadOption.PublisherThread, false, NullEventSubscriptionFilter );
public bool NullEventSubscriptionFilter<T>( T param )
{
  return true;
}

Which is what I’m going to do now.

Advertisements
About

Christian is a software architect/developer. He lives in Germany, reads a lot, and likes cycling.

Tagged with: ,
Posted in Coding
2 comments on “PRISM event aggregator: more leaky than it seems
  1. […] 4.0: System.Tuple : Sam Gentile's Blog Eloquent JavaScript is an interactive, free JavaScript book PRISM event aggregator: more leaky than it seems « greenicicle Ajaxian » JavaScript asynchronous method queue chaining jQuery Templates and Data Linking jQuery […]

  2. Nice spot. I’ve got the same issue with an app that I’m working on, only that even after fixing this, the weak references are staying alive….

    Looking through the PRISM code though, it looks like this bug only affects the filter reference – the action reference is always set correctly as a weak reference; later on in GetExecutionStrategy() of EventSubscription.cs, both the Action and Filter reference must be valid to publish to the subscription, otherwise it gets removed. So I think that whilst the code is wrong, it shouldn’t keep references alive.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: