【问题标题】:Memory spike when reading multiple image files读取多个图像文件时的内存峰值
【发布时间】:2014-08-16 06:27:33
【问题描述】:

我正在尝试制作一个文件资源管理器,而我一直遇到的一个问题是尝试修复当我从图像中加载多个缩略图时出现的内存峰值。这是我认为它所在的部分(这都包含在后台工作人员中):

static string[] imageType = new string[] { "jpeg", "jpg", "png", "bmp" };

List<string> filesList = new List<string>();

foreach (FileInfo file in fileList)
    filesList.Add(file.FullName);

string[] files = filesList.ToArray();

NumericComparer nc = new NumericComparer();
Array.Sort(files, nc);

foreach (string file in files)
{
    Application.OpenForms["MDC_Explorer"].Invoke(new MethodInvoker(() =>
    {
        Application.DoEvents();
    }));

    Panel d = new Panel();
    d.Size = new Size(parent.Width / 5 - 10, 100);//Image Height: 70px
    d.Location = new Point(left, top);
    d.Tag = file;
    d.MouseEnter += new EventHandler(item_MouseEnter);
    d.MouseLeave += new EventHandler(item_MouseLeave);
    d.BackgroundImageLayout = ImageLayout.Stretch;

    Label l = new Label();
    FileInfo fileInfo = new FileInfo(file);
    l.Text = Path.GetFileNameWithoutExtension(fileInfo.FullName);
    l.Size = new Size(d.Width, 25);
    l.Location = new Point(0, 75);
    l.TextAlign = ContentAlignment.TopCenter;
    l.ForeColor = Color.FromArgb(255, 90, 90, 90);
    l.Font = new Font(parent.Font.FontFamily, 10, FontStyle.Regular);
    l.BackColor = Color.Transparent;
    l.MouseEnter += new EventHandler(item_MouseEnter);
    l.MouseLeave += new EventHandler(item_MouseLeave);
    l.MouseClick += new MouseEventHandler(item_MouseClick);

    d.Controls.Add(l);

    PictureBox pb = new PictureBox();

    string path = file;

    if (Path.GetExtension(file).Replace(".", "") == "lnk")
    {
        IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell();
        IWshRuntimeLibrary.IWshShortcut link = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(file);
        path = link.TargetPath;
    }

    if (!File.Exists(path) && path.Contains("Program Files (x86)"))
        path = path.Replace("Program Files (x86)", "Program Files");

    Bitmap bmp = Path.GetExtension(path).Replace(".", "") == "exe" ? Icon.ExtractAssociatedIcon(path).ToBitmap() : (imageType.Contains(Path.GetExtension(path).Replace(".", "")) ? new Bitmap(Image.FromStream(new MemoryStream(File.ReadAllBytes(path))), new Size(d.Width - 20, 80)) : new Bitmap(GetLargeIconForExtension(Path.GetExtension(path)).ToBitmap()));
            bigThumbnail.Add(bmp);

    int fp = (parent.Width / 4) * 3 - 50;
    smallThumbnail.Add(new Bitmap(bmp, new Size((fp / 5), 80)));

    pb.BackgroundImage = bmp;
    pb.BackgroundImageLayout = ImageLayout.Center;
    pb.Size = new Size(d.Width - 20, 80);
    pb.BackColor = Color.Transparent;
    pb.Location = new Point(10, 10);
    pb.MouseEnter += new EventHandler(item_MouseEnter);
    pb.MouseLeave += new EventHandler(item_MouseLeave);
    pb.MouseClick += new MouseEventHandler(item_MouseClick);

    d.Controls.Add(pb);

    if (left + (d.Width * 2) + 5 >= parent.Width)
    {
        top += d.Height + 5;
        left = 5;
    }
    else
        left += d.Width + 5;

    Application.OpenForms["MDC_Explorer"].Invoke(new MethodInvoker(() =>
    {
        parent.Controls.Add(d);
    }));
}

对不起,如果我提供了很多代码,但我认为错误在于它获取缩略图并将其放入位图中,但我不确定如何降低内存使用量。

【问题讨论】:

  • 您的最终目标(或者更好的设计目标)到底是什么?
  • 您预计内存使用量会增加多少?
  • 最终目标:减少内存使用,使其可以在较低的系统规格上运行。我不明白你的意思,但抓取缩略图时它从大约 30k 到 200k。
  • 这可能更适合代码审查,除非它导致内存不足异常......
  • "...(或者更好,设计目标)?"...

标签: c# image winforms memory thumbnails


【解决方案1】:

您正在创建图像和位图而不释放它们,因此在垃圾收集器销毁这些 bmp 之前,它们都在内存中。

此外,在某些情况下,您正在读取内存中的所有图像文件,将其加载到流中,然后将其传递给 Image.FromStream,这样做比 Image.FromFile 好得多。

代替:

Bitmap bmp = Path.GetExtension(path).Replace(".", "") == "exe" ?     
Icon.ExtractAssociatedIcon(path).ToBitmap() : 
(imageType.Contains(Path.GetExtension(path).Replace(".", "")) ? new 
Bitmap(Image.FromStream(new MemoryStream(File.ReadAllBytes(path))), 
new Size(d.Width - 20, 80)) : new Bitmap(GetLargeIconForExtension(Path.GetExtension(path))
.ToBitmap()));

这样做:

        Bitmap bmp;

        string ext = Path.GetExtension(path);

        if (ext == ".exe")
        {

            Icon ico = Icon.ExtractAssociatedIcon(path);
            bmp = ico.ToBitmap();
            ico.Dispose();

        }
        else
        {

            if (imageType.Contains(ext.Replace(".", "")))
            {

                Image img = Image.FromFile(path);
                bmp = new Bitmap(img, new Size(d.Width - 20, 80));
                img.Dispose();
            }
            else
            {

                Icon ico = GetLargeIconForExtension(ext);
                bmp = ico.ToBitmap();
                ico.Dispose();

            }

        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-24
    • 1970-01-01
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多