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
TestMdiChild.cs
TestMdiChild.Designer.cs
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
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.csnamespace
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