gpt4 book ai didi

c# - 字体导致自定义控件中的 GDI 泄漏

转载 作者:太空宇宙 更新时间:2023-11-03 11:04:52 26 4
gpt4 key购买 nike

我创建了一个自定义控件,如下所示。

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);
}

我有两个表单 Form1 和 Form2。此 TextBoxEx 添加到 Form2。单击 Form1 中的按钮时显示 Form2。

连续显示和关闭 Form2 会导致我的应用程序发生 GDI 泄漏。经GDI检测工具(Bear.exe)分析,发现是该字体导致GDI泄漏。

我的问题是,

  1. 为什么调用了TextBoxEx的Dispose()方法后字体没有释放(当关闭Form2时,会自动调用TextBoxEx的Dispose()方法)。
  2. 如何解决由字体引起的 GDI 泄漏?。(在TextBoxEx的Dispose()方法中不能调用Font.Dispose(),因为它在构造函数中抛出“参数无效”异常)。

最佳答案

大多数绘图对象的创建成本非常。例如,创建一支笔或画笔的时间不会超过一微秒。这就是为什么您应该始终在开始绘图时创建它们并在完成绘图后处理它们的原因。 using 声明强烈鼓励您这样做。

然而,字体类很难。创建它们并不便宜,Windows 需要做大量工作才能将您要求的字体映射到可用的字体集并加载 TrueType 大纲。 Winforms 有一个解决方案,它缓存 字体。您将在第一次使用字体时承担创建字体的费用。但是您可以随后处理它,但字体对象保留在字体缓存中。下次您创建相同的字体时,您将从缓存中获得非常便宜的副本。

这也是 WPF 中的一个问题,更是如此,因为它具有更丰富的字体支持,包括对 OpenType 轮廓的支持。它以不同的方式解决,WPF 使用完全独立的进程来缓存字体。充当任何 WPF 应用程序的字体缓存服务器。您会在任务管理器中看到此进程,它是 PresentationFontCache.exe 进程。

无论如何,任何类型的泄漏诊断程序都会被这个缓存弄糊涂。它会认为您的应用程序正在泄漏字体,它会看到存储在缓存中的字体。只有当使用的字体数量无限制地增长并最终导致程序崩溃时,才会出现真正的泄漏。易于测试,Windows 的限额较低,一个进程不能创建超过 10,000 个绘图对象。因此,如果确实存在泄漏,则无需长时间运行测试程序即可达到该配额。您也可以在任务管理器中看到这一点。查看 + 选择列,勾选 GDI 对象复选框。确保您的测试程序的数量稳定,不会超过几百个,无论大小。

关于c# - 字体导致自定义控件中的 GDI 泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16261951/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com