Fully featured low overhead profiler for Java EE and Java SE platforms.
Ultimate profiling and monitoring solution for Gradle, Maven, Ant, JUnit and TestNG.
Easy to use performance and memory profiler for .NET framework.

Event handler not releasing reference?

Moderators: Vladimir Kondratyev, Anton Katilin

Event handler not releasing reference?

Postby mike » Tue Apr 28, 2009 4:13 am

I've learned the hard way about event handlers in .NET, and how a long-lived event source can hold on to a reference to a short-lived event sink, thereby preventing it from being garbage-collected. For this reason, I now use weak delegates whenever possible. I use the Pvax.WeakDelegates library (http://www.codeproject.com/KB/architecture/observable_property_patte.aspx).

But even with weak delegates, I've run into a case where an event handler is firing in an object that (as far as I can tell from the YourKit profiler) is not being referenced anywhere. I have reproduced the issue in a simple .NET 2.0 WinForms project in VS2005.

I have a form that contains 3 buttons. btnCreate creates an instance of a user control and adds it to the Controls collection of a panel. btnDelete calls a .Clear() method on the user control and removes it from the panel. btnChange changes the value of an application setting, defined under Properties / Settings.settings in the solution explorer. Here's the code in Form1:

Code: Select all
public partial class Form1 : Form
{
   public Form1()
   {
      InitializeComponent();
   }

   private void btnCreate_Click( object sender, EventArgs e )
   {
      if ( panel1.Controls.Count == 0 )
      {
         UserControl1 ctrl = new UserControl1();
         panel1.Controls.Add(ctrl);
      }
   }

   private void btnDelete_Click( object sender, EventArgs e )
   {
      UserControl1 ctrl = (UserControl1)panel1.Controls[0];
      ctrl.Clear();
      panel1.Controls.Clear();
   }

   private void btnChange_Click( object sender, EventArgs e )
   {
      Properties.Settings.Default.MySetting++;
   }
}


The user control (which contains a label) subscribes to the Properties.Settings.Default.PropertyChanged event by means of a weak delegate, and the handler for this event sets the label text to a string held in a member variable of type List<string>. This list is set to null by the .Clear() method when btnDelete is clicked. Here's the code in the user control:

Code: Select all
public partial class UserControl1 : UserControl
{
   private List<string> _list = new List<string>();

   public UserControl1()
   {
      InitializeComponent();
      _list.Add("foo");
      Properties.Settings.Default.PropertyChanged +=
      (PropertyChangedEventHandler)Pvax.WeakDelegates.WeakDelegateDecorator.AddHandler(
      Properties.Settings.Default, "PropertyChanged",
      new PropertyChangedEventHandler(Settings_PropertyChanged));
   }

   public void Clear()
   {
      _list = null;
   }

   public void Settings_PropertyChanged( object sender, EventArgs e )
   {
      label1.Text = _list[0];
   }
}


At runtime, if you click btnCreate, the user control appears. If you then click btnDelete, it disappears. If you then click btnChange, you get a NullReferenceException in UserControl1's Settings_PropertyChanged event handler, because _list is null.

I have used the YourKit .NET Profiler to see what objects exist in memory after clicking each button in turn. After clicking btnCreate and taking a snapshot, the Profiler's object explorer tells me that I have an instance of Form1, an instance of Properties.Settings, and an instance of UserControl1. This is what I expect. After clicking btnDelete and taking another snapshot, the instance of UserControl1 is no longer listed in the object explorer. This is also what I expect, because nothing is referencing the user control any more.

So why does the event handler fire when I then click btnChange? The weak delegate should notice that the event sink no longer exists and silently unsubscribe from the event. I haven't had any problems with weak delegates in any other situation before.

I really can't understand what's going on in this case.
mike
 
Posts: 1
Joined: Tue Apr 28, 2009 1:34 am

Re: Event handler not releasing reference?

Postby Arizona » Fri Aug 07, 2009 5:54 am

Hi,

Very interested, the event handler fire when btnChange, it seem be one small bug. :shock:
Arizona
 
Posts: 1
Joined: Fri Aug 07, 2009 5:49 am


Return to .NET Profiler

Who is online

Users browsing this forum: No registered users and 1 guest