Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8607511
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 12, 20262026-06-12T03:22:26+00:00 2026-06-12T03:22:26+00:00

I’m developing a Windows Forms application (.NET 4.0) in c# using Visual c# express

  • 0

I’m developing a Windows Forms application (.NET 4.0) in c# using Visual c# express 2010. I’m having trouble freeing up memory allocated to UserControls I’m no-longer using.

The problem:

I have a FlowLayoutPanel, where custom UserControls are displayed. The FlowLayoutPanel displays search results and so on, so the collection of UserControls that are displayed must be repeatedly updated.

Before every new set of these UserControls are created and displayed, Dispose() is called on all the Controls currently contained in my FlowLayoutPanel’s ControlCollection (Controls property), then Clear() is called on the same ControlCollection.

This doesn’t seem to be sufficient to dispose of the resources used by the UserControls because with each new set of UserControls which is created and added to my ControlCollection, nor do my UserControls seem to be claimed by garbage collection. The application’s memory usage climbs sharply over a short period of time, then reaches a plateau until I display another list. I’ve also analysed my application with .NET Memory Profiler, which reports a number of possible memory leaks (See lower section.)

What I think is going wrong:

I was wrong. The problem was a bug caused by using a foreach construct to iterate through a ControlCollection and calling Dispose() on its controls, which Hans Passant describes in his answer.


The problem seems to be caused by ToolTip used in my UserControls. When I removed these, my UserControls appeared to be claimed by garbage collection. This was confirmed by .NET memory profiler. Problem 1 and 6 from my earlier test (see lower section) no longer appeared and it reported a new problem:

Undisposed instances (release resource and remove external references)
7 types have instances that have been garbage collected without being properly disposed.
Investigate the types below for more information.

ChoiceEditPanel (inherited), NodeEditPanel (inherited), Button, FlowLayoutPanel, Label, > Panel, TextBox

Even with the ToolTip’s reference gone, which isn’t a long-term solution, there is still the problem of deterministically disposing of my UserControls when I no longer need them. However, isn’t as important as removing the references to the ToolTips.

Code and more details

I use a UserControl called NodesDisplayPanel which acts as a wrapper to a FlowLayoutPanel. Here is the method in my NodesDisplayPanel class which is used to clear all Controls from my FlowLayoutPanel:

public void Clear() {
    foreach (Control control in flowPanel.Controls) {
        if (control != NodeEditPanel.RootNodePanel) {
            control.Dispose();
        }
    }
    flowPanel.Controls.Clear();
    // widthGuide is used to control the widths of the Controls below it,
    // which have Dock set to Dockstyle.Top
    widthGuide = new Panel();
    widthGuide.Location = new Point(0, 0);
    widthGuide.Margin = new Padding(0);
    widthGuide.Name = "widthGuide";
    widthGuide.Size = new Size(809, 1);
    widthGuide.TabIndex = 0;
    flowPanel.Controls.Add(widthGuide);
}

These methods are used to add Controls:

public void AddControl(Control control) {
    flowPanel.Controls.Add(control);
}
public void AddControls(Control[] controls) {
    flowPanel.Controls.AddRange(controls);
}

Here is the method that instantiates new NodeEditPanels and adds them to my FlowLayoutPanel, via my NodesDisplayPanel. This method is from ListNodesPanel (as seen in screenshot below), one of several UserControls that instantiate and add NodeEditPanels:

public void UpdateNodesList() {
    Node[] nodes = Data.Instance.Nodes;
    Array.Sort(nodes,(IComparer<Node>) comparers[orderByDropDownList.SelectedIndex]);
    if ((listDropDownList.SelectedIndex == 1)
        && (nodes.Length > numberOfNodesNumUpDown.Value)) {
        Array.Resize(ref nodes,(int) numberOfNodesNumUpDown.Value);
    }
    NodeEditPanel[] nodePanels = new NodeEditPanel[nodes.Length];
    for (int index = 0; index < nodes.Length; index ++) {
        nodePanels[index] = new NodeEditPanel(nodes[index]);
    }
    nodesDisplayPanel.Clear();
    nodesDisplayPanel.AddControls(nodePanels);
}

This is my custom innitilization method for my ListNodesPanel UserControl. Hopefully it will make the UpdateNodesList() method a bit clearer:

private void NonDesignerInnitialisation() {
    this.Dock = DockStyle.Fill;
    listDropDownList.SelectedIndex = 0;
    orderByDropDownList.SelectedIndex = 0;
    numberOfNodesNumUpDown.Enabled = false;
    comparers = new IComparer<Node>[3];
    comparers[0] = new CompareNodesByID();
    comparers[1] = new CompareNodesByNPCText();
    comparers[2] = new CompareNodesByChoiceCount();
}

In case there are any known issues with particular Windows.Forms Components, Here’s a list of all the types of Components that are used in each of my UserControls:

ChoiceEditPanel:

  • Panel
  • Label
  • Button
  • TextBox
  • ToolTip

NodeEditPanel

  • ChoiceEditPanel
  • FlowLayoutPanel
  • Panel
  • Label
  • Button
  • Textbox
  • ToolTip

I am also using the i00SpellCheck library for some of the TextBoxes

Possible issues initially reported by .NET Memory Profiler:

I got my application to display 50 or so NodeEditPanels, twice, the second list having identical values to the first but being different instances. .Net Memory Profiler compared the states of the application after the first and second operation, and produced this list of possible problems:

  1. Direct EventHandler roots
    One type has instances that are directly rooted by an EventHandler. This can indicate that an EventHandler has not been properly removed.
    Investigate the type below for more information.

    ToolTip

  2. Disposed instances
    2 types have instances that have been disposed but not GCed.
    Investigate the types below for more information.

    System.Drawing.Graphics, WindowsFont

  3. Undisposed instances (release resource)
    6 types have instances that have been garbage collected without being properly disposed.
    Investigate the types below for more information.

    System.Drawing.Bitmap, System.Drawing.Font, System.Drawing.Region, Control.FontHandleWrapper, Cursor, WindowsFont

  4. Direct delegate roots
    2 types have instances that are directly rooted by a delegate. This can indicate that the delegate has not been properly removed.
    Investigate the types below for more information.

    System.__Filters, __Filters

  5. Pinned instances
    2 types have instances that are pinned in memory.
    Investigate the types below for more information.

    System.Object, System.Object[]

  6. Indirect EventHandler roots
    53 types have instances that are indirectly rooted by an EventHandler. This can indicate that the EventHandler has not been properly removed.
    Investigate the types below for more information.

    , ChoiceEditPanel, NodeEditPanel, ArrayList, Hashtable, Hashtable.bucket[], Hashtable.KeyCollection, Container, Container.Site, EventHandlerList, (…)

  7. Undisposed instances (memory/resource utilization)
    3 types have instances that have been garbage collected without being properly disposed.
    Investigate the types below for more information.

    System.IO.BinaryReader, System.IO.MemoryStream, UnmanagedMemoryStream

  8. Duplicate instances
    71 types have duplicate instances (492 sets, 741,229 duplicated bytes). Duplicate instances can cause unnecessary memory consumption.
    Investigate the types below for more information.

    GPStream (8 sets, 318,540 duplicated bytes), PropertyStore.IntegerEntry[] (24 sets, 93,092 duplicated bytes), PropertyStore (10 sets, 53,312 duplicated bytes), PropertyStore.SizeWrapper (16 sets, 41,232 duplicated bytes), PropertyStore.PaddingWrapper (8 sets, 38,724 duplicated bytes), PropertyStore.RectangleWrapper (28 sets, 32,352 duplicated bytes), PropertyStore.ColorWrapper (13 sets, 30,216 duplicated bytes), System.Byte[] (3 sets, 25,622 duplicated bytes), ToolTip.TipInfo (10 sets, 21,056 duplicated bytes), Hashtable (2 sets, 20,148 duplicated bytes), (…)

  9. Empty weak reference
    The WeakReference type has instances that are no longer alive.
    Investigate the WeakReference type for more information.

    System.WeakReference

  10. Undisposed instances (clear references)
    One type has instances that have been garbage collected without being properly disposed.
    Investigate the type below for more information.

    EventHandlerList

  11. Large instances
    2 types have instances that are located in the large object heap.
    Investigate the types below for more information.

    Dictionary.DictionaryItem[], System.Object[]

  12. Held duplicate instances
    25 types have duplicate instances that are held by other duplicate instances (136 sets, 371,766 duplicated bytes).
    Investigate the types below for more information.

    System.IO.MemoryStream (8 sets, 305,340 duplicated bytes), System.Byte[] (7 sets, 248,190 duplicated bytes), PropertyStore.ObjectEntry[] (10 sets, 40,616 duplicated bytes), Hashtable.bucket[] (2 sets, 9,696 duplicated bytes), System.String (56 sets, 8,482 duplicated bytes), EventHandlerList.ListEntry (6 sets, 4,072 duplicated bytes), List (6 sets, 4,072 duplicated bytes), EventHandlerList (3 sets, 3,992 duplicated bytes), System.EventHandler (6 sets, 3,992 duplicated bytes), DialogueEditor.Choice[] (6 sets, 3,928 duplicated bytes), (…)

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-12T03:22:27+00:00Added an answer on June 12, 2026 at 3:22 am
    foreach (Control control in flowPanel.Controls) {
        if (control != NodeEditPanel.RootNodePanel) {
            control.Dispose();
        }
    }
    flowPanel.Controls.Clear();
    

    This is a pretty classic Winforms bug, many programmers have been bitten by it. Disposing a control also removes it from the parent’s Control collection. Most .NET collection classes trigger an InvalidOperationException when iterating them changes the collection but that wasn’t done for the ControlCollection class. The effect is that your foreach loop skips elements, it only disposes the even-numbered controls.

    You already discovered the problem, but made it considerably worse by calling Controls.Clear(). Extra-specially nasty because the garbage collector will not finalize the controls that are removed that way. After the native window handle for a control is created, it will stay referenced by an internal table that maps Window handles to controls. Only destroying the native window removes the reference from that table. That never happens in code like this, calling Dispose() is a rock hard requirement. Very unusual in .NET.

    The solution is to iterate the Controls collection backwards so that disposing controls doesn’t affect what you iterate. Like this:

    for (int ix = flowPanel.Controls.Count-1; ix >= 0; --ix) {
        var ctl = flowPanel.Controls[ix];
        if (ctl != NodeEditPanel.RootNodePanel) ctl.Dispose();
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

link Im having trouble converting the html entites into html characters, (&# 8217;) i
We're building an app, our first using Rails 3, and we're having to build
I'm having trouble keeping the paragraph square between the quote marks. In firefox the
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I am reading a book about Javascript and jQuery and using one of the
I'm using v2.0 of ClassTextile.php, with the following call: $testimonial_text = $textile->TextileRestricted($_POST['testimonial']); ... and
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
We are using XSLT to translate a RIXML file to XML. Our RIXML contains
I have thousands of HTML files to process using Groovy/Java and I need to

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.