Tuesday, March 23, 2010

Avoid memory leaks in .NET

There is enough said about memory leaks in .NET when using events. BING or Google for "weak event". The problem is that when you have an observer for some object's event myObj.MyEvent when observer is no longer needed myObj.MyEvent still keeps reference to observer's event handling delegate. Thus preventing observer from being garbage collected. The solution is to always unsubscribe observer from any events it might listen to before disposing it. Well, this is easier said than done.

One way to deal with this issue is to create weak event references. There are many patterns and frameworks which support weak events such as EventAggregator in Prism or in WPF MVVM app template there is WeakEventReference.

The other way is to keep reference to event handler and always unsubscribe before disposing. This could be tricky.

The third way is very simple but covers only a subset of all possible event scenarios. This is what I will show in here. Suppose you have a handler which is no longer needed after event is fired. Then you can use lambda expression or anonymous delegate and keep reference to it only until it is in the scope. Here is an example. In this example I actually have two handlers which are not needed after either one of them is executed.  

   1: // declare a reference to event handler
   2: EventHandler myEvent1Result = null;
   3: EventHandler myEvent2Result = null;
   5: // when MyEvent1 fires we handle it like so 
   6: myEvent1Result = (s, ea) =>
   7:     {
   8:         // unsubscribe from events immedeately
   9:         (s as MyObject).MyEvent1Event -= myEvent1Result;
  10:         (s as MyObject).MyEvent2Event -= myEvent2Result;
  12:         // do some other processing
  13:         //....
  14:     };
  16: // when MyEvent2 fires we handle it like so 
  17: myEvent2Result = (s, ea) =>
  18:    {
  19:        // unsubscribe from events immedeately
  20:        (s as MyObject).MyEvent1Event -= myEvent1Result;
  21:        (s as MyObject).MyEvent2Event -= myEvent2Result;
  23:        // do some other processing
  24:        //....
  25:    };
  27: // once we created event handlers now we can subscribe them.
  28: myObject.MyEvent1Event += myEvent1Result;
  29: myObject.MyEvent2Event += myEvent2Result; 

Happy coding!

No comments:

Post a Comment