读取多个图像文件时内存峰值

时间:2014-06-25 15:35:28

标签: c# image winforms memory thumbnails

我试图创建一个文件浏览器,我一直坚持的一个问题是尝试修复当我从图像加载多个缩略图时发生的内存峰值。这是我认为它所在的部分(这全部包含在后台工作者中):

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

很抱歉,如果我提供了很多代码,但我相信错误是它获取缩略图并将其放入位图,但我不确定如何降低内存使用量。

1 个答案:

答案 0 :(得分:2)

您正在创建图像和位图而不进行处理,因此在垃圾收集器销毁这些垃圾邮件之前,它们会在内存中。

此外,在某些情况下,您正在读取内存中的所有图像文件,将其加载到流中然后将其传递给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();

            }

        }