有人可以告诉我出了什么问题吗?
删除大量代码以找到我们的GDI对象泄漏(使用任务管理器并观察“GDI对象”列增长到10,000并且我们的应用程序崩溃)我将代码缩减为仅.net代码而没有任何自定义业务代码。我们仍然在解决这个问题。
我创建了一个测试应用来复制问题,该问题具有以下基本行为。
现在正在以特定方式设置150次启动的表单(让我们调用表单“BadForm”。这是一个静态数据表,它绑定到表单上的组合框。
BadForm上有一个comboBox和一个计时器。以下是表单的代码:
using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
namespace GDIObjectLeakTest
{
public partial class MyForm :Form
{
public static DataTable CachedNodeType = new DataTable();
public MyForm()
{
InitializeComponent();
this.comboBox1.SelectedIndexChanged += new EventHandler(this.comboBox1_SelectedIndexChanged);
this.Font = new Font("Modern No. 20", 8.249999F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0))); ;
comboBox1.DataSource = CachedNodeType;
}
private void timer1_Tick(object sender, EventArgs e)
{
Close();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{ }
}
}
以下是运行测试的应用程序主窗体的代码。它上面有2个按钮。 Button1运行BadForm 150次。按钮2运行垃圾收集器100次(我猜一次或两次对我来说不够好)(我使用垃圾收集器只是为了证明存在/不存在问题)。
private void button1_Click(object sender, EventArgs e)
{
try
{
for(int i = 0; i < 150; i++)
{
//new SearchForm().Show();
new MyForm().Show();
}
} catch(Exception ee)
{
throw;
}
}
private void button2_Click(object sender, EventArgs e)
{
for(int i = 0; i < 100; i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
答案 0 :(得分:2)
尝试将其添加到dispose方法的顶部(在设计器文件中):
comboBox1.DataSource = null;
答案 1 :(得分:0)
我在这里看到两个潜在的问题:
如果创建实现IDisposable
的对象的实例,则必须在其上调用Dispose方法,或将其包含在using
块中。 表单实现IDisposable ,因此您的代码应如下所示:
using (Form myform = new Form())
{
myform.Show();
} //frees resource by calling Dispose automatically
否则,你会看到你在这里看到的内存泄漏,因为你正在创建表单的新实例,但是你永远不会释放它的资源。由于终结器在BCL中的写入方式,垃圾收集最终可能会在WinForms中为您释放Windows资源,但调用Dispose会立即执行此操作。
您正在创建一个新的Font
对象,并在每次初始化表单时将其分配给Font属性。并不是说这一定是坏事(设计器生成的代码会大量执行此操作),但每个新的Font
实例都占用一个GDI句柄,除非你调用Font.Dispose,否则不会自动释放它。我的猜测是你要留下另一个可能没有正确使用Disposed的Font对象。如果要对这些对象进行巨大的数量,您可能希望以某种方式对其进行优化(例如通过共享Font实例)。 In at least one case,不调用Dispose on fonts会导致内存泄漏。
答案 2 :(得分:0)
您使用的是Font对象,它是一个GDI对象,在您处置它之前不会被释放。 使用Font对象和using语句,或者在FormClose事件上调用Font.Dispose。