我在 Windows 应用程序中发现轻微的内存泄漏。我在我的应用程序中使用 DevExpress XtraForm。我看到的是该表格的一个实例始终保存在内存中。如果您多次打开同一个表单,它仍然保留上次打开的表单的引用。
前任。如果您在应用程序中打开 10 个不同的表单并关闭所有它们,它仍然不会释放分配给它的内存,因为一些奇怪的“MdiClient 对象引用 LayoutEventArgs 对象”。幸运的是,它保留了每种类型的单个项目的引用。
以下是 Redgate 内存分析器输出的链接。
https://dl.dropboxusercontent.com/u/2781659/Memory%20Leak.pdf https://dl.dropboxusercontent.com/u/2781659/Memory%20Leak.pdf
在上面的图表中,DepartmentsForm 已被处置,但无法被 GC,因为 LayoutEventArgs 的affectedComponent 成员引用了它。
如果您发现任何明显错误,请指出。
根据我的经验,在 Windows 窗体中,在某些情况下,可以将已释放的控件缓存在LayoutEventArgs
对象,它看起来像是 WinForms 中的某种小错误。
一些细节:
每个实例的System.Windows.Forms.Control
type 包含一个私有成员变量LayoutEventArgs
type - cachedLayoutEventArgs
。并且,LayoutEventArgs
通常包含对某些特定控件的引用。您可以通过 Reflector 清楚地看到所有这些事实。并且,有时,cachedLayoutEventArgs
由于某些原因,子控件处置时未清除字段不影响父控件的布局过程。您可以使用 mdi 父窗体来模拟这种情况,方法是在关闭其子级时暂停 MdiClient 的控件布局:
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;
}
}
}
附:无论如何,我建议您联系DevExpress 支持 https://www.devexpress.com/Support/Center/对此,确认你所描述的内存泄漏与其控件无关并得到最终的解决方案。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)