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

C#创建PictureBox时触发OutOfMemoryException问题求助

批量创建PictureBox加载PNG触发OutOfMemoryException问题

问题详情

  • 文件夹内共55张PNG图片,单张最大78KB,其余多在30-50KB区间
  • 循环创建PictureBox并添加到FlowLayoutPanel时,执行PictureBox picture = new()抛出内存不足异常
  • 已尝试切换x64平台、启用gcallowverylargeobjects配置、手动调用GC.Collect(),均未解决
  • 分批加载(如仅4张)无异常,图片数量越多,异常触发概率越高
  • 使用场景:窗体加载时展示所有图片;用户添加GIF链接后,清空面板重新加载以避免重复
  • 计算最大图片内存占用:32位深×293宽度×254高度=2381504字节(约2.27MB)

核心代码片段

if (file.FullName.EndsWith(FileFormats[0]))
{
    PictureBox picture = new()
    {
        Name = "picture",
        Size = new(45, 45),
        Image = Image.FromFile(file.FullName),
        SizeMode = PictureBoxSizeMode.Zoom
    };
    picture.Click += Pic_Click;
    flowLayoutPanel1.Controls.Add(picture);
}

解决方案

1. 加载时缩小图片并释放文件句柄

Image.FromFile会锁定文件且加载原始尺寸图片,即便PictureBox只显示45×45,内存中仍保留原始大图。改用流加载并缩小到显示尺寸,大幅降低内存占用:

using (var fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
using (var originalImage = Image.FromStream(fs))
{
    // 缩小到PictureBox的显示尺寸
    using (var resizedBitmap = new Bitmap(45, 45))
    {
        using (var g = Graphics.FromImage(resizedBitmap))
        {
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            g.DrawImage(originalImage, 0, 0, 45, 45);
        }
        // 转换为非索引格式Bitmap,避免后续内存泄漏
        var displayImage = new Bitmap(resizedBitmap);
        var picture = new PictureBox
        {
            Name = "picture",
            Size = new Size(45, 45),
            Image = displayImage,
            SizeMode = PictureBoxSizeMode.Zoom
        };
        picture.Click += Pic_Click;
        flowLayoutPanel1.Controls.Add(picture);
    }
}

2. 清空面板时彻底释放资源

清空FlowLayoutPanel时,必须手动释放每个PictureBox的Image资源和控件本身,否则GC无法及时回收内存:

foreach (Control ctrl in flowLayoutPanel1.Controls.OfType<PictureBox>().ToList())
{
    ctrl.Click -= Pic_Click; // 移除事件绑定
    ctrl.Image?.Dispose(); // 释放图片资源
    ctrl.Dispose(); // 释放控件
}
flowLayoutPanel1.Controls.Clear();

3. 缓存重复图片(可选)

如果存在重复的图片路径,缓存已缩小的图片,避免重复加载占用内存:

// 类级别缓存字典
private readonly Dictionary<string, Image> _imageCache = new();

// 加载图片逻辑
if (!_imageCache.TryGetValue(file.FullName, out var cachedImage))
{
    // 执行上面的缩小加载逻辑,将displayImage存入缓存
    _imageCache[file.FullName] = displayImage;
}
else
{
    // 使用缓存的图片创建PictureBox
    var picture = new PictureBox
    {
        Name = "picture",
        Size = new Size(45, 45),
        Image = cachedImage,
        SizeMode = PictureBoxSizeMode.Zoom
    };
    picture.Click += Pic_Click;
    flowLayoutPanel1.Controls.Add(picture);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 10:40:49