I' currently debugging a big Winforms application that's got some memory leak issues. I use the .NET memory profiler and so far I've been able to find some of those leaks and solve them. But now I am faced with a problem which I am not sure is a problem, and if it is one I don't know how to solve it.
After running my application for like 1 min (which is not a lot considering normal users could use it for hours),.NET memory profiler shows me around 100-200 instances of different controls from the Krypton Toolkit, and this number is increasing if I keep going (they are never garbage collected, because it appears they are still being referenced somewhere). Now if I check the root path of those instances and they all look like:
I don't know where to look in my code to make these instances be de-referenced correctly when they are not needed anymore, since I don't know what is still referencing the control. I know the place where the KryptonButtonEx gets created, and from what I understand the ViewManager is created by this button, but still I don't see what I can do about it. For those who are interested, the code to create the button is this:
KryptonButton newControlButton = new KryptonButton();
newControlButton.Tag = mtActivityControl;
newControlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
newControlButton.AutoSize = true;
newControlButton.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly;
newControlButton.ButtonStyle = ComponentFactory.Krypton.Toolkit.ButtonStyle.ListItem;
newControlButton.Location = new System.Drawing.Point(3, 3);
newControlButton.Name = string.Format("controlButton{0}", mtActivityControl.SymbolicName);
newControlButton.Size = new System.Drawing.Size(96, 23);
newControlButton.StateCommon.Content.Image.ImageH = ComponentFactory.Krypton.Toolkit.PaletteRelativeAlign.Near;
newControlButton.StateCommon.Content.ShortText.TextH = ComponentFactory.Krypton.Toolkit.PaletteRelativeAlign.Near;
newControlButton.TabIndex = 5;
StringBuilder buttonText = new StringBuilder();
buttonText.Append(Path.GetFileName(mtActivityControl.ControlName));
/*if (mtActivityControl.SymbolicName.Length != 0)
{
buttonText.Append(" (");
buttonText.Append(mtActivityControl.SymbolicName);
buttonText.Append(")");
}*/
newControlButton.Text = buttonText.ToString();
newControlButton.Values.ExtraText = "";
newControlButton.Values.Image = null;
newControlButton.Values.ImageStates.ImageCheckedNormal = null;
newControlButton.Values.ImageStates.ImageCheckedPressed = null;
newControlButton.Values.ImageStates.ImageCheckedTracking = null;
newControlButton.Values.Text = buttonText.ToString();
newControlButton.Click += new System.EventHandler(this.controlsButton_Click);
and even though it is not necessary from what my research told me, I unhook the event like this in the Dispose function:
newControlButton.Click -= new System.EventHandler(this.controlsButton_Click);
So my question is:
Is it possible that Krypton itself keeps a reference to my controls which leads to some memory not being freed (which could be ok if it is a limited amount of memory used for keeping an object pool or something like that, but could be a problem if it is an uncontrolled memory leak)? If it doesn't come from Krypton, do you have an idea where to look to destroy those instances correctly?
Many thanks!
EDIT:
I just noticed that the class KryptonButtonEx doesn't come from Krypton but from my app. But I don't think it changes anything to the question since the only thing it does is override the GetPreferredSize function:
/// <summary>
/// An extended/fixed KryptonButton which handles resizing correctly.
/// </summary>
public class KryptonButtonEx : ComponentFactory.Krypton.Toolkit.KryptonButton
{
/// <summary>
/// Gets the size of the preferred.
/// </summary>
/// <param name="proposedSize">Size of the proposed.</param>
/// <returns></returns>
public override Size GetPreferredSize(Size proposedSize)
{
// Do we have a manager to ask for a preferred size?
if (ViewManager != null)
{
// Ask the view to peform a layout
Size retSize = ViewManager.GetPreferredSize(Renderer, proposedSize);
// Apply the maximum sizing
if (MaximumSize.Width > 0) retSize.Width = Math.Min(MaximumSize.Width, retSize.Width);
if (MaximumSize.Height > 0) retSize.Height = Math.Min(MaximumSize.Height, retSize.Width);
// Apply the minimum sizing
if (MinimumSize.Width > 0) retSize.Width = Math.Max(MinimumSize.Width, retSize.Width);
if (MinimumSize.Height > 0) retSize.Height = Math.Max(MinimumSize.Height, retSize.Height);
return retSize;
}
else
{
// Fall back on default control processing
return base.GetPreferredSize(proposedSize);
}
}
}