Using RadMenu in an MDI Parent & Child with button menu items leaks memory

7 posts, 1 answers
  1. Fred
    Fred avatar
    17 posts
    Member since:
    Oct 2010

    Posted 29 Nov 2010 Link to this post

    Hello,

    I've got this memory leak, could you guys give an explanation/workaround? I've made the simplest test case (see below), factors for the bug to occur (that I already discovered):

    - it's an MDI form situation with parent & child
    - the child is maximized (the menu items are added into one menubar)
    - the menu item provided by the client is a menu button
    - a textbox is on the child form

    TestMdiParent.cs
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
     
    using Telerik.WinControls.UI;
     
    namespace MenuMemoryLeak
    {
        public partial class TestMdiParent : Telerik.WinControls.UI.RadForm
        {
            public TestMdiParent()
            {
                InitializeComponent();
     
            }
     
            //NOTE this stuff with the backgroundworker is just to repeatedly close/open the form, I know it's not fully correct but the bug occurs nevertheless
     
            BackgroundWorker myWorker = new BackgroundWorker() { WorkerReportsProgress = true, WorkerSupportsCancellation = false };
            TestMdiChild myMdiChild;
     
            private void TestMdiParent_Shown(object sender, EventArgs e)
            {
                myWorker.DoWork += delegate
                {
                    int count = 0;
                    while(true)
                    {
                        ++count;
                        myWorker.ReportProgress(count);
                        System.Threading.Thread.Sleep(1000);
                    }
                };
     
                myWorker.ProgressChanged += delegate
                {
                    if(myMdiChild != null)
                    {
                        myMdiChild.Close();
                        System.GC.Collect();
                    }
                    myMdiChild = new TestMdiChild() { MdiParent = this };
                    myMdiChild.Show();
                };
     
                myWorker.RunWorkerAsync();
            }
        }
    }

    TestMdiParent
    .Designer.cs
    namespace MenuMemoryLeak
    {
        partial class TestMdiParent
        {
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.IContainer components = null;
     
            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
     
            #region Windows Form Designer generated code
     
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                this.testMenuItem = new Telerik.WinControls.UI.RadMenuItem();
                this.testParentMenu = new Telerik.WinControls.UI.RadMenu();
                ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
                ((System.ComponentModel.ISupportInitialize)(this.testParentMenu)).BeginInit();
                this.SuspendLayout();
                //
                // testMenuItem
                //
                this.testMenuItem.Name = "testMenuItem";
                this.testMenuItem.Text = "Parent";
                //
                // TestMdiParent
                //
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(902, 523);
                //
                // testParentMenu
                //
                this.testParentMenu.Items.AddRange(new Telerik.WinControls.RadItem[] {
                this.testMenuItem});
                this.testParentMenu.Location = new System.Drawing.Point(0, 0);
                this.testParentMenu.Name = "testParentMenu";
                this.testParentMenu.Size = new System.Drawing.Size(902, 24);
                this.testParentMenu.TabIndex = 1;
                this.testParentMenu.Text = "radMenu1";
                this.Controls.Add(this.testParentMenu);
                this.IsMdiContainer = true;
                this.Name = "TestMdiParent";
                //
                //
                //
                this.RootElement.ApplyShapeToControl = true;
                this.Text = "TestMdiParent";
                this.ThemeName = "ControlDefault";
                this.Shown += new System.EventHandler(this.TestMdiParent_Shown);
                ((System.ComponentModel.ISupportInitialize)(this.testParentMenu)).EndInit();
                ((System.ComponentModel.ISupportInitialize)(this)).EndInit();
                this.ResumeLayout(false);
                this.PerformLayout();
     
            }
     
            #endregion
     
            private Telerik.WinControls.UI.RadMenuItem testMenuItem;
            private Telerik.WinControls.UI.RadMenu testParentMenu;
     
        }
    }

    TestMdiChild.cs
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using Telerik.WinControls;
     
    namespace MenuMemoryLeak
    {
        public partial class TestMdiChild : Telerik.WinControls.UI.RadForm
        {
            public TestMdiChild()
            {
                InitializeComponent();
     
                //NOTE required for bug to occur
                this.WindowState = FormWindowState.Maximized;
            }
        }
    }


    TestMdiChild.Designer.cs
    namespace MenuMemoryLeak
    {
        partial class TestMdiChild
        {
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.IContainer components = null;
     
            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
     
            #region Windows Form Designer generated code
     
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                this.testMenuButtonItem = new Telerik.WinControls.UI.RadMenuButtonItem();
                this.testChildMenu = new Telerik.WinControls.UI.RadMenu();
                this.testTextBox = new Telerik.WinControls.UI.RadTextBox();
                ((System.ComponentModel.ISupportInitialize)(this.testChildMenu)).BeginInit();
                ((System.ComponentModel.ISupportInitialize)(this.testTextBox)).BeginInit();
                ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
                this.SuspendLayout();
                //
                // testMenuButtonItem
                //
                this.testMenuButtonItem.Name = "testMenuButtonItem";
                this.testMenuButtonItem.Text = "Child";
                //
                // testChildMenu
                //
                this.testChildMenu.AllowMerge = false;
                this.testChildMenu.IsMainMenu = false;
                this.testChildMenu.Items.AddRange(new Telerik.WinControls.RadItem[] {
                this.testMenuButtonItem});
                this.testChildMenu.Location = new System.Drawing.Point(0, 0);
                this.testChildMenu.Name = "testChildMenu";
                this.testChildMenu.Size = new System.Drawing.Size(467, 24);
                this.testChildMenu.TabIndex = 2;
                this.testChildMenu.Text = "radMenu1";
                //
                // testTextBox
                //
                this.testTextBox.Location = new System.Drawing.Point(22, 23);
                this.testTextBox.Name = "testTextBox";
                this.testTextBox.Size = new System.Drawing.Size(100, 20);
                this.testTextBox.TabIndex = 1;
                this.testTextBox.TabStop = false;
                this.testTextBox.Text = "test";
                //
                // TestMdiChild
                //
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(467, 268);
                this.Controls.Add(this.testChildMenu);
                this.Controls.Add(this.testTextBox);
                this.Name = "TestMdiChild";
                //
                //
                //
                this.RootElement.ApplyShapeToControl = true;
                this.Text = "TestMdiChild";
                this.ThemeName = "ControlDefault";
                ((System.ComponentModel.ISupportInitialize)(this.testChildMenu)).EndInit();
                ((System.ComponentModel.ISupportInitialize)(this.testTextBox)).EndInit();
                ((System.ComponentModel.ISupportInitialize)(this)).EndInit();
                this.ResumeLayout(false);
                this.PerformLayout();
     
            }
     
            #endregion
     
            private Telerik.WinControls.UI.RadMenuButtonItem testMenuButtonItem;
            private Telerik.WinControls.UI.RadMenu testChildMenu;
            private Telerik.WinControls.UI.RadTextBox testTextBox;
        }
    }

    If you call the parent MDI form and let it run a bit you should see the GDI objects increase by one each second and never get released.

    If you know a solution/workaround, thanks a lot

    Frederik
  2. Fred
    Fred avatar
    17 posts
    Member since:
    Oct 2010

    Posted 30 Nov 2010 Link to this post

    I'm using the latest Q3 release BTW, problem has been checked on multiple computers (win7 & winxp)
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Richard Slade
    Richard Slade avatar
    3000 posts
    Member since:
    May 2009

    Posted 30 Nov 2010 Link to this post

    Hello Fred, 

    I haven't been able to sort this out for you at the moment, but I am able to replicate it. As you said, without the WinDowState line, the GC seems to collect correctly. I have included a screenshot of the object retention list for the TestMdiChild from ANTS. I'll look into it further as soon as I can. 
    Richard
  5. Fred
    Fred avatar
    17 posts
    Member since:
    Oct 2010

    Posted 30 Nov 2010 Link to this post

    Hi Richard,

    thanks a lot for confirming the leak and your memory analysis (though it only says for me the problem is somewhere in Telerik), for now it is easily worked around by by not using a button menu item but I'd be interesting to have this fixed in a future version or hear about another way to avoid it. Funny thing if you replace the textbox in the client MDI form with eg. a grid, the problem does not occur anymore, so the occurence of the leak is really tied to it being a textbox (or seems to be indirectly related to it being a textbox).

    Greetings

    Frederik
  6. Answer
    Peter
    Admin
    Peter avatar
    1148 posts

    Posted 02 Dec 2010 Link to this post

    Hello Fred,

    Thank you for writing.

    I have updated your Telerik points for bringing this issue to our attention and I would like to thank you for the time taken to help us to investigate the case. We will do our best to address it for the upcoming SP release.

    Thank you for your time.

    Regards,
    Peter
    the Telerik team
    Get started with RadControls for WinForms with numerous videos and detailed documentation.
  7. Matjaž Kofol
    Matjaž Kofol avatar
    13 posts
    Member since:
    Dec 2006

    Posted 08 Dec 2010 Link to this post

    I am also experiencing MemoryLeaks problem with Telerik WinForms controls.
    Have MDI application and on one Form in main panel I add and remove two UserControls (depending on button action). I am also attaching and removing events  to them dynamically (before Clear() is called I also remove attached events). I also called Dispose() on every Control inside my panel before calling Clear() method and then I add again the one of these two user controls to this panel.

    Results:
    My applications (the same form) is working slower and slower each time until it is unusable (this form and application itself).

    Regards
    Matjaž
  8. Peter
    Admin
    Peter avatar
    1148 posts

    Posted 11 Dec 2010 Link to this post

    Hello Matjaž Kofol,

    Thank you for writing.

    Could you share with us more information (or send a sample project) about the controls you are using in this application, because the provided information is not enough for us to locate the issue.

    In addition, I want to share with you that the Garbage Collector releases the instance of RadControls slower than it would free a less complex control. The reason is that RadControl is a second generation Garbage Collector object. In case you would like to release the memory instantly after the subform is closed, you should call GC.Collect() manually. More information about the garbage collection generations can be found here.

    I am looking forward for your response.

    Kind regards,
    Peter
    the Telerik team
    Get started with RadControls for WinForms with numerous videos and detailed documentation.
Back to Top
UI for WinForms is Visual Studio 2017 Ready