C# 字体导致自定义控件中的GDI泄漏
我创建了一个自定义控件,如下所示C# 字体导致自定义控件中的GDI泄漏,c#,winforms,custom-controls,gdi,resource-leak,C#,Winforms,Custom Controls,Gdi,Resource Leak,我创建了一个自定义控件,如下所示 public partial class TextBoxEx : TextBox { public TextBoxEx() { InitializeComponent(); Font = Utility.normalFont; } protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); } } //A utility c
public partial class TextBoxEx : TextBox
{
public TextBoxEx()
{
InitializeComponent();
Font = Utility.normalFont;
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
}
//A utility class to initialize font.
class Utility
{
internal static Font normalFont = new Font("Arial", 18);
}
我有两张表格,表格一和表格二。此TextBoxEx已添加到Form2中。单击表单1中的按钮时,我正在显示表单2
持续显示和关闭Form2会导致我的应用程序中出现GDI泄漏。使用GDI检测工具(Bear.exe)进行分析后,发现字体导致GDI泄漏
我的问题是,
无论如何,任何类型的泄漏诊断程序都会被这个缓存搞糊涂。它会认为你的应用程序正在泄漏字体,它会看到存储在缓存中的字体。只有当使用的字体数量无限增长并最终导致程序崩溃时,才会出现真正的漏洞。易于测试,Windows强加的配额很低,一个进程不能创建超过10000个图形对象。因此,如果存在真正的漏洞,您不需要长时间运行测试程序来达到该配额。您也可以在任务管理器中看到这一点。查看并选择列,勾选GDI对象复选框。确保您的测试程序的数字是稳定的,并且不会超过几百个,给定或接受。Font不应释放,因为它在静态normalFont变量中引用。我不认为这是一个漏洞。@Alex:当我对这行代码“Font=Utility.normalFont;”进行注释时,漏洞就消失了。我认为这种字体保存的是一份副本,而不是参考资料。我可以通过在TextBoxEx的Dispose()方法中设置Font=null来解决GD泄漏问题。但这是一个好主意吗?字体是引用类型,所以不会被复制。我认为你的泄漏分析器提供了错误的信息。阅读Hans Passant的回答,你在任何地方都找不到更好的专家:)@Alex:但当我在TextBoxEx的Dispose()方法中设置Font=null时,GDI泄漏消失了。我已经和TaskManager联系过了。很有趣。无论如何,在Dispose中将字体设置为NULL是可以的。当我连续打开和关闭表单时,TaskManager中的GDI计数会不断增加1。但当我在TextBoxEx的Dispose()方法中设置Font=null时,GDI泄漏消失。是否建议在TextBox控件的Dispose()方法中将字体设置为NULL?当我连续打开和关闭Form2时,TaskManager中的GDI计数会不断增加1。将GDI计数增加到某个计数(70-80)后,它将自动减少到某个计数,依此类推。当我向form2中添加500 TextBoxEx并持续打开和关闭表单时,TaskManager中的GDI计数将为504。它没有增加。在TextBoxEx的Dispose()方法中设置Font=null时,TaskManager中的GDI计数将在关闭表单时重置为4。是建议在TextBox控件的Dispose()方法中将字体设置为NULL,还是应该忽略它并信任GC收集GDI对象?我确实看到了类似的奇怪现象。但是,它不会爆炸,GDI对象计数会不断下降并备份,而无需在Dispose()方法中执行任何操作或将字体引用设置回null。等我有时间的时候,我会再挖一些,不过你肯定没问题。谢谢你的回复。当我处理所有其他绘图对象(钢笔、画笔、位图等)时,我决定离开控件的字体对象,让GC来收集它。无论如何,我会继续关注这个帖子,如果你看到任何有趣的事情,我会发帖子。