Page 1 of 1

PgSqlDataTable Disposing Failed

Posted: Sun 21 Aug 2016 08:38
by chris901
Hello,

i have 2 Forms (Form1 and Form2).

In Form1 i create a new Form2 with a click on a button and dispose that form with another button:

Code: Select all

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

        private Form _form;

        private void button1_Click(object sender, EventArgs e)
        {
            _form = new Form2();
            _form.Show();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            _form.Dispose();
        }
    }


Form2 has an Timer and PgSqlDataTable component placed on it: Image

Form 2 also introduces the disposing events for both the Timer and the SqlDataTable:

Code: Select all

    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            timer1.Disposed += delegate { MessageBox.Show("timer1 - Disposed"); };
            pgSqlDataTable1.Disposed += delegate { MessageBox.Show("pgSqlDataTable1 - Disposed"); };
        }
    }
However when i dispose the Form2 in Form1 (button2_Click) only the Timer gets disposed and the message shown.

Could it be that SqlDataTable doesn't get disposed correctly?!

Thanks.

Re: PgSqlDataTable Disposing Failed

Posted: Thu 25 Aug 2016 10:10
by Pinturiccio
We have reproduced the issue. We will investigate it and post here about the results as soon as possible.

Re: PgSqlDataTable Disposing Failed

Posted: Mon 29 Aug 2016 17:53
by chris901
Thanks for fixing this. Can't wait to get rid of that memory leak. Got any timeframe about the hotfix?

Re: PgSqlDataTable Disposing Failed

Posted: Tue 30 Aug 2016 14:37
by Pinturiccio
When the Dispose method is called for a form, the following code is executed:

Code: Select all

protected override void Dispose(bool disposing) {
	if (disposing && (components != null)) {
		components.Dispose();
	}
	base.Dispose(disposing);
}
When a Timer object is created, it is added to the components container. So, when a Form is disposed, the Dispose method is called for all objects in the components container, including the Timer object.

When the PgSqlDataTable object is added to a Form, the PgSqlDataTable object is not added to the components container. So, when the Form with the PgSqlDataTable object is disposed, the Dispose method is not called for PgSqlDataTable. It is a designed behavior; the same behavior can be noticed in the Microsoft DataSet component as well, for example. You should call the Dispose method of PgSqlDataTable yourself.

Re: PgSqlDataTable Disposing Failed

Posted: Wed 31 Aug 2016 02:52
by chris901
I see.

I've also looked it up on SO and found this interesting question:
http://stackoverflow.com/questions/5555 ... nts-object

So it really seems to be the best way to dispose it manually because you can't always rely on the designer.

I've also found on SO a way to iterate through all components:

Code: Select all

http://stackoverflow.com/questions/38310117/delphi-to-c-sharp-winforms-iterate-through-form-components-on-form

private IEnumerable<Component> EnumerateComponents()
{
            return from field in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                   where typeof(Component).IsAssignableFrom(field.FieldType)
                   let component = (Component)field.GetValue(this)
                   where component != null
                   select component;
}
However my problem is that PgSqlDataTable never gets listed there?
Timer, PgSqlConnection, PgSqlCommand, PgSqlDataAdapter and all the other components get listed there and I can dispose them in e.g. the form desctructor.

Do you have an idea why PgSqlDataTable doesn't appear in the result of EnumerateComponents() listed there? Isn't it a descendant of IComponent or some other issue?

Re: PgSqlDataTable Disposing Failed

Posted: Mon 05 Sep 2016 15:57
by Pinturiccio
chris901 wrote:Do you have an idea why PgSqlDataTable doesn't appear in the result of EnumerateComponents() listed there?
The reason is that PgSqlConnection, PgSqlCommand, PgSqlDataAdapter classes are descendants of the Component class, and PgSqlDataTable class is not. PgSqlDataTable class is inherited from System.Data.Table class, which is not inherited from the Component class.

Thus, PgSqlDataTable does not meet the condition: typeof(Component)