You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

System.Drawing命名空间中哪些类会计入系统GDI对象总数?

理清System.Drawing中哪些对象计入系统GDI对象总数

你提到的这个问题确实是GDI资源管理里的高频疑惑——毕竟搞不清哪些对象占GDI计数,很容易踩资源泄漏的坑。我结合官方文档和实际测试经验给你梳理清楚:

哪些对象会计入系统GDI对象总数?

这些对象直接对应Windows原生GDI句柄,创建时会向系统申请GDI资源,必须手动释放(或通过using自动释放):

  • Pen:完全符合,它对应GDI的HPEN句柄,你创建1000个未释放的Pen,去任务管理器(详细信息列里勾选「GDI对象」)看进程的GDI计数,会明显增加1000左右,这也是你测试代码能验证的点
  • Brush及其派生类(SolidBrush、LinearGradientBrush等):对应GDI的HBRUSH句柄
  • Font:对应HFONT句柄,字体资源的占用很容易被忽略,尤其频繁创建Font又不释放的场景
  • Bitmap:大部分场景下会计入,比如从本地文件加载、通过Graphics绘制生成的Bitmap,对应GDI的HBITMAP句柄;不过纯托管内存的Bitmap(比如通过Bitmap(int width, int height)创建的)可能不会,但保险起见还是要释放
  • Region:对应HRGN句柄,用于区域裁剪时会占用GDI资源
  • Graphics:它包装了GDI的HDC(设备上下文),虽然HDC的计数在任务管理器里可能单独体现,但本质上属于GDI资源范畴;注意从控件获取的Graphics(比如Control.CreateGraphics())不需要手动释放,但自己创建的(比如Graphics.FromImage())必须释放

哪些对象不会计入?

这些是纯托管对象,没有绑定原生GDI句柄,不会占用系统GDI计数:

  • Matrix:只是托管端的变换矩阵计算对象,完全在.NET托管内存中运行,和系统GDI资源无关
  • GraphicsPath:它是托管端的路径描述容器,只有当你调用Graphics.DrawPath()这类渲染方法时,才会临时创建GDI资源用于绘制,但GraphicsPath本身不会计入GDI对象总数
  • 基础值类型(Point、Size、Rectangle等):纯托管内存存储,和GDI资源完全不沾边

关键提醒:避免GDI泄漏

因为GDI对象是系统级资源,每个进程默认有GDI对象上限(通常是10000左右),超过后会出现绘制异常、程序崩溃等问题。所以一定要用using语句自动释放实现了IDisposable的GDI对象,比如:

using (var redPen = new Pen(Color.Red, 2))
using (var solidBrush = new SolidBrush(Color.Blue))
{
    // 执行绘制操作
    g.DrawLine(redPen, 0, 0, 100, 100);
    g.FillRectangle(solidBrush, new Rectangle(50, 50, 200, 100));
}

这样代码块结束时,Pen和Brush会自动调用Dispose()释放对应的GDI句柄,不会造成泄漏。

内容的提问来源于stack exchange,提问作者glopes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:23:08