C# Windows窗体内存泄漏
我在我的windows应用程序中看到一个轻微的内存泄漏。我在应用程序中使用DevExpress XtraForm。我看到的是表单的一个实例总是被保存在内存中。如果多次打开同一表单,它仍会保留上次打开表单的引用 例如,如果在应用程序中打开10个不同的窗体并关闭所有窗体,由于某些奇怪的“MdiClient对象引用LayoutEventArgs对象”,它仍然不会释放分配给它的内存。幸运的是,它保留了每种类型的单个项的引用 下面是指向Redgate内存探查器输出的链接 在上面的图表中,DepartmentsForm已禁用,但无法进行GCD,因为LayoutEventArgs的affectedComponent成员引用了它C# Windows窗体内存泄漏,c#,.net,memory-leaks,devexpress,devexpress-windows-ui,C#,.net,Memory Leaks,Devexpress,Devexpress Windows Ui,我在我的windows应用程序中看到一个轻微的内存泄漏。我在应用程序中使用DevExpress XtraForm。我看到的是表单的一个实例总是被保存在内存中。如果多次打开同一表单,它仍会保留上次打开表单的引用 例如,如果在应用程序中打开10个不同的窗体并关闭所有窗体,由于某些奇怪的“MdiClient对象引用LayoutEventArgs对象”,它仍然不会释放分配给它的内存。幸运的是,它保留了每种类型的单个项的引用 下面是指向Redgate内存探查器输出的链接 在上面的图表中,Departme
如果您看到任何明显的错误,请给出建议。根据我的经验,Windows窗体中存在一些情况,即释放的控件可以缓存在
LayoutEventArgs
对象中,并且看起来像WinForms中的某种小错误
一些细节:System.Windows.Forms.Control
类型的每个实例都包含LayoutEventArgs
type-cachedLayoutEventArgs
的私有成员变量。而且,LayoutEventArgs
通常包含对某些特定控件的引用。通过反射器,您可以清楚地看到所有这些事实。而且,有时,当子控件由于某些原因不影响父控件的布局过程时,cachedLayoutEventArgs
字段不会被清除。您可以使用mdi父窗体模拟这种情况,方法是在关闭其子窗体时挂起mdi客户端的控件布局:
public partial class MdiParentForm : Form {
public MdiParentForm () {
InitializeComponent(); // this.IsMdiContainer = true
}
void buttonAddMdiChild_Click(object sender, EventArgs e) {
MdiChildForm f = new MdiChildForm();
f.MdiParent = this;
f.Show();
}
void buttonCloseMdiChild_Click(object sender, EventArgs e) {
MdiClient client = GetMdiClient(this);
client.SuspendLayout();
if(ActiveMdiChild != null)
ActiveMdiChild.Close();
client.ResumeLayout(false);
// !!! At this point the MdiClient.cachedLayoutEventArgs contains the reference to disposed control (leak)
}
static MdiClient GetMdiClient(Form frm) {
if(frm != null) {
foreach(Control ctrl in frm.Controls) {
if(ctrl is MdiClient)
return (MdiClient)ctrl;
}
}
return null;
}
}
class MdiChildForm : Form { }
有一个简单的解决方法-通过触发PerformLayout
方法,可以有效地清除“缓存”实例:
class MdiChildForm : Form {
MdiClient parent;
protected override void OnParentChanged(EventArgs e) {
base.OnParentChanged(e);
var mdiClient = Parent as MdiClient;
if(mdiClient != parent) {
if(parent != null)
parent.PerformLayout();
parent = mdiClient;
}
}
}
另外,我建议您就此联系,以确保您描述的内存泄漏与他们的控件无关,并获得最终解决方案。如果没有任何代码,就无法判断,即使这样,我怀疑可能很难提供帮助。我已随问题提供了对象保留图。