Continuously adding and removing to flow-layout panel win forms

1.9k views Asked by At

I have a c# win forms application which has a flowLayoutPanel in it.

I need to update all the children in this panel every second.

here is my current code which gets called in a system timer every 1 seconds:

   public void RefreshReceiversPage()
    {
        if (checkBox_enableReceivers.Checked)
        {
            var receivers = OutgoingReceiverManager.GetCopyOfActiveRecieverHolders();

            for (int i = 0; i < flowLayoutPanel_receivers.Controls.Count; i++)
            {
                var tmp = flowLayoutPanel_receivers.Controls[i];
                flowLayoutPanel_receivers.Controls[i].Dispose();
                tmp.Dispose();
            }
            flowLayoutPanel_receivers.Controls.Clear();

            foreach (var item in receivers.ToList())
            {
                var tmpUc = new ucReceiverItem(item);
                if (flowLayoutPanel_receivers != null)
                {
                    try
                    {
                        flowLayoutPanel_receivers.Controls.Add(tmpUc);
                    }
                    catch
                    {
                    }
                }
            }
            receivers = null;
        }            
    }

now this code works perfectly for about 2 minutes and then all of a sudden I start getting error creating window handle Hence the reason for my try catch in the code above.

But after this happens the pane view goes funny and I cant recover it without starting up the program again.

I have searched high and low and I cant seem to find anything on the exception being thrown?

All that I can think is that im maybe not disposing of object properly and that its running out of memory some where?

Does any one have any suggestions or solutions?

EDIT:

here is UCRecieverItem:

public partial class ucReceiverItem : UserControl
{
    public ucReceiverItem(ReceiverHolder item)
    {
        InitializeComponent();
        ConstructItem(item);
        item = null;
    }

    private void ConstructItem(ReceiverHolder item)
    {
        label_name.Text = item.ReceiverDb.Name;
        label_numberOfConnections.Text = item.ReceiverOutgoingConnectionManager.GetNumberOfConnections().ToString();
        label_mrFilters.Text = item.ReceiverDb.MrFilters;
        label_multipleConnections.Text = item.ReceiverDb.MultipleConnections.ToString();
        //
        int count = item.GetActiveBufferCount();
        int size = item.GetActiveBufferSize();
        //
        label_bufferCount.Text = count + @" / " + size;
        progressBar_buffer.Maximum = size;
        progressBar_buffer.Minimum = 0;
        progressBar_buffer.Value = count;
    }
}
1

There are 1 answers

1
LarsTech On BEST ANSWER

This code is a problem:

for (int i = 0; i < flowLayoutPanel_receivers.Controls.Count; i++)
{
  var tmp = flowLayoutPanel_receivers.Controls[i];
  flowLayoutPanel_receivers.Controls[i].Dispose();
  tmp.Dispose();
}
flowLayoutPanel_receivers.Controls.Clear();

It is only disposing half of the controls in the container. The other half get removed by the Controls.Clear(); call, but those controls do not get disposed — so they still exist and are using up memory.

Doing this every second compounds the problem: that's potentially a lot of controls.

The immediate work-around would be to properly dispose of the controls:

while (flowLayoutPanel_receivers.Controls.Count > 0) {
  flowLayoutPanel_receivers.Controls[0].Dispose();
}

After that, I would question the need to do this every second — seems like a harsh environment for a user to work in.