none
Should System.ComponentModel.Container() be used in a Custom Control RRS feed

  • Question

  • I have developed a simple custom control which is effectively a custom button with a timer, derived from Control. I am unsure of using "components = new System.ComponentModel.Container()". Since the control uses a timer, should it be added to the components container? i.e. components.Add(timer); ? If so, how is it disposed, components.Dispose() is only called if Dispose(true) is called, which i dont? Or should i have a destructor ~MyComponent() which calls timer.Dispose().

    In short, when do you use a "components = new Container()" and "components.Add()" in a custom control.

    Also, if my control uses Graphics, Brush & Pen objects, should Dispose() be called on them and if so where. In the deconstructor? Or do you leave it up to the garbage collector?

    Thanks.

    • Moved by Mike Dos ZhangModerator Wednesday, April 6, 2011 8:48 AM clr related question (From:Windows Forms General)
    Monday, April 4, 2011 3:07 PM

Answers

  •  

    The Component class has its finalizer method (~Component()), if we don't invoke Dispose method explicitly, the method will be called by GC when the component object is un-reachable (to release the object's unmanaged resource), and the managed part of the component object will be released by next GC (gen1 GC) operation;

     

    Anyway, Application.Exit() terminated current process, when a process exit, OS clears all resources used by the process, make sure there will be no resource leak.


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by J Marchant Monday, April 11, 2011 6:58 AM
    Friday, April 8, 2011 9:43 AM

All replies

  • It is not necessary to use the Container on your custom control. I believe the component object will dispose of it's internal components when it's disposed. You can handle any objects that need disposing in the user controls dispose method just as easily.

    Again, any object that supports IDisposable (Brush,Pen,Graphics, etc etc) can be disposed of in the user controls dispose method. (And you should most definately make sure that dispose is being called on these)

    AFAIK when you Close() a form, it sends Dispose(true). This can be proven/disproven by putting a break point at the dispose method and see what value it holds (Dispose(bool)) when the form is closing.

    Monday, April 4, 2011 5:27 PM
  • Thanks for the info, i noticed that Dispose(true) was not getting called when i use Application.Exit() to quit my app! If i call Form.Close() then Dispose(true) is called. I thought Application.Exit() was a controlled way to exit your app but its not disposing everything! I use it as i have multiple forms in my app.

    Why doesnt Application.Exit() dispose of everything by passing true to Dispose() and exit correctly? Is this a .NET bug?

    I am still unsure about the use of ComponentModel.IContainer as i have seen other examples of a control which use a timer that is added to the components.container and other controls which declare a container to use.

    Also, is it ok to use a deconstructor e.g. ~MyControl() to dispose of resources in my control, or should you always use Dispose()? What would be the difference, is it bad .NET practice to use C++ style deconstructors?

    Thanks in advance.

    Tuesday, April 5, 2011 7:30 AM
  • What do you expect Dispose is doing?

    Don't think it releases your object, it releases the unmanaged resources from it (and sometimes something more if the method is not well used).

    It is a method which is included in components so mainly classes which derive from that (forms classes almost all included the smallest component) have that method. (The interface (contract) is Idisposible).

    (Sometimes it does completely nothing, it is very much related to Win32 development, WPF does not have it in its presentations)

    In the drawing classes it is recommended because that uses many unmanaged resources so there is a small change you run out of that is always written (I have never seen that however in any message in the Net newsgroups or forums).


    Success
    Corc



    Tuesday, April 5, 2011 7:34 AM
  • Yes, i understand that, but you havent really answered any of my questions:-

    1. Why doesnt Application.Exit() dispose of everything by passing true to Dispose() and exit correctly? Is this a .NET bug? i.e. Dispose(true) is never called.

    2. What is the correct use for ComponentModel.IContainer in a custom control. i.e When & why.

    3. Is using C++ style deconstructors acceptable for a custom control or should you only use the Dispose() method.

    Remeber my point that Dispose(true) is not always being called, depending on the exit method used, therefore not everything is released.

    Tuesday, April 5, 2011 8:01 AM
  • Hi J Marchant,

    I think this question is almost a object dispose CLR related topic, so I moved this thread here.

    The CLR experts will give you the expert explanation on this question.

     

    Best wishes,


    Mike [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by J Marchant Wednesday, April 6, 2011 10:46 AM
    • Unmarked as answer by J Marchant Wednesday, April 6, 2011 10:48 AM
    Wednesday, April 6, 2011 8:50 AM
    Moderator
  • Additionally to my post above, if anyone can answer those questions:-

    Why is it that Application.Exit() causes the destructor to be called i.e. ~MyComponent(), yet Dispose(true) is not called?

    The opposite apply to Form.Close() :-

    Why is it that Form.Close() causes Dispose(true) to be called, yet ~MyComponent() destructor is not?

    So i am not sure where to dispose of my resources and that potential memory leaks are occurring depending on the exit method used.

    Wednesday, April 6, 2011 3:16 PM
  •  

    We can use Reflector tool to find out how the System.ComponentModel.Component class implemented, I extra some methods here:

     

    ~Component()

    {

        this.Dispose(false);

    }

     

                // Summary:

                //     Releases all resources used by the System.ComponentModel.Component.

    public void Dispose()

    {

        this.Dispose(true);

        GC.SuppressFinalize(this);

    }

     

     

                //

                // Summary:

                //     Releases the unmanaged resources used by the System.ComponentModel.Component

                //     and optionally releases the managed resources.

                //

                // Parameters:

                //   disposing:

                //     true to release both managed and unmanaged resources; false to release only

                //     unmanaged resources.

    protected virtual void Dispose(bool disposing)

    {

        if (disposing)

        {

            lock (this)

            {

                if ((this.site != null) && (this.site.Container != null))

                {

                    this.site.Container.Remove(this);

                }

                if (this.events != null)

                {

                    EventHandler handler = (EventHandler) this.events[EventDisposed];

                    if (handler != null)

                    {

                        handler(this, EventArgs.Empty);

                    }

                }

            }

        }

    }

     

    The destructor, also called Finalizer method, can only be invoked by GC; Application.Exit() will terminate current process, hence trigger a GC operation, GC will invoke the ~Component() method to release unmanaged resource, which result in the calling of Dispose(false) method.

     

    Developers can invoke Dispose() method explicitly to release an object, which calls the Dispose(true). System.Windows.Forms.Form.Close() method looks like:

     

    public void Close()

    {

        if (base.GetState(0x40000))

        {

            throw new InvalidOperationException(SR.GetString("ClosingWhileCreatingHandle", new object[] { "Close" }));

        }

        if (base.IsHandleCreated)

        {

            this.closeReason = CloseReason.UserClosing;

            base.SendMessage(0x10, 0, 0);

        }

        else

        {

            base.Dispose();

        }

    }

    You can see that the base.Dispose() method is called, that's why Dispose(true) method is invoked.


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, April 7, 2011 4:18 AM
  • Thanks, thats a lot clearer now. One last question then, When adding a new component to your project the following code is created:-

            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }

            private void InitializeComponent()
            {
                components = new System.ComponentModel.Container();
            }

    Now, if something is added to 'components' and Application.Exit() is called, which does not cause Dispose(true) to be called, what happens to 'components'? You can see that they are only Disposed if 'disposing == true'. So what has happened to the components resources? Are they ever released?

    Thursday, April 7, 2011 7:42 AM
  •  

    The Component class has its finalizer method (~Component()), if we don't invoke Dispose method explicitly, the method will be called by GC when the component object is un-reachable (to release the object's unmanaged resource), and the managed part of the component object will be released by next GC (gen1 GC) operation;

     

    Anyway, Application.Exit() terminated current process, when a process exit, OS clears all resources used by the process, make sure there will be no resource leak.


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by J Marchant Monday, April 11, 2011 6:58 AM
    Friday, April 8, 2011 9:43 AM