Click here to Skip to main content
15,885,309 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi

I seem to have run in kind of a race condition. This is the very simplified version of the problem. (In reality there are several layers inbetween, the controls are no Buttons, but also inherited from Control etc.) I _need_ to remove and dispose my controls after e.g. a leave event as below.
If I click on button1 I get an ObjectDisposedException, because it needs to finish something. If I click on button2 it obviuously works.
How can I find out, when it is ready to be disposed? Or how can I force a Control to finish all it needs to do before disposing?
A possible solution should work for all inheritances of Control.
(My first maybe naive try was just to stop all messages as in code below. Nor helps an Application.DoEvents())

THANK YOU!

using System;
using System.Windows.Forms;

namespace Test
{
    static class Program
    {
        static void Main()
        {
            Application.Run(new TestForm());
        }

        public class TestForm : Form
        {

            myButton button1;
            myButton button2;

            public TestForm()
            {
                TextBox tb = new TextBox();
                Controls.Add(tb);


                button1 = new myButton();
                button1.Text = "button1";
                button1.Location = new System.Drawing.Point(tb.Right, 0);
                Controls.Add(button1);

                button2 = new myButton();
                button2.Text = "button2";
                button2.Location = new System.Drawing.Point(button1.Right, 0);
                Controls.Add(button2);

                tb.Leave += new EventHandler(tb_Leave);
            }

            void tb_Leave(object sender, EventArgs e)
            {
                Controls.Remove(button1);
                button1.WillBeDisposed = true;

                //this will throw an ObjectDisposedException if the Leave event was caused by clicking on button1
                //this will NOT throw an ObjectDisposedException if the Leave event was caused by clicking on button2

                //How can I find out at which point of time the button (or any other Control) can be safely disposed, or how can I force button1 to finish all it needs to do?

                button1.Dispose();
            }
        }

        public class myButton : Button
        {
            internal bool WillBeDisposed = false;
            protected override void WndProc(ref Message m)
            {
                if (WillBeDisposed) return; //doesn't help
                base.WndProc(ref m);
            }
        }
    }
}
Posted
Updated 20-Nov-12 3:08am
v2

1 solution

If you really have to:

1. Explicitly implement IDisposable in class myButton.
2. If the parent class implements Dispose(), make sure you call the parent version in the first line of your function.
3. Don't forget to call GC.SuppressDispose() (or similar, I don't remember the exact name); google for 'IDisposable implementation'.

But you don't really have to.
You only have to make disposable objects if they contain resources (database connections, sockets, file handles, GDI handles, ...).
Forms and controls are not supposed to manage resources: that's what the MVC pattern (and all those derived from it) is all about. Only classes in the Model should manage resources.

Hope this helps,

Pablo.
 
Share this answer
 
Comments
vmp5 21-Nov-12 8:06am    
Thanks. I'd still be interested in what's happening in the Control.Dispose() implementation and what it tries to access. But you're right, the dispose was a bit misused in my original case, so I could workaround it.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900