Show a lot of images with really low memory using in C#?

懵懂的女人 提交于 2019-12-11 09:42:00

问题


I have a form in which I dynamically create 8 PictureBoxes in a Panel in which I show 8 different images, one every PictureBox. Images are 50Kb Jpeg. The problem is that I want to allow user to see also 300 pictures,that's like 38 panels, but every time I LOAD images into PictureBoxes my program uses 5-7Mb of Ram memory MORE.( I see it from the Windows' task manager) How can i reduce that increment? My Pictures aren't that big, I only want to show a preview, i don't care about quality. Here is how i CREATE PictureBoxes:

private void buttonAdd_Click(object sender, EventArgs e)
{     
  Panel pan = new Panel();
  PictureBox pic1 = new PictureBox();
  pic1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
  pic1.Location = new System.Drawing.Point(208, 5);
  pic1.Name = "panel" + ctr.Count().ToString() + "pictureBox1";
  pic1.Size = new System.Drawing.Size(100, 100);
  pic1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
  ///
  /// Same thing other 7 times with differents name and location
  ///      
  pan.Location = new System.Drawing.Point(12, 55);
  pan.Name = "panel" + ctr.Count().ToString();
  pan.Size = new System.Drawing.Size(1088, 129);
  pan.TabIndex = 0;
  pan.AllowDrop = true;
  pan.BackColor = System.Drawing.SystemColors.ControlLight;
  pan.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;           
  pan.Controls.Add(pic1);
  ///
  /// Same thing other 7 times 
  ///        
  this.Controls.Add(pan);
  }

And here is how i fill them:

void buttonClickEvent(object sender, EventArgs e)
    {
        string[] files= Directory.GetFiles("mylocalpath");
        foreach(string x in files)
        {
            string imgIndex= x.Remove(0,x.LastIndexOf("_")+1).Remove(1);
            PictureBox pic=pictureBox1; 
            //I get it everytime from imgIndex and sender's parent,
            //too much code to show now
            pic.ImageLocation = x;
        }

    }

回答1:


You can ignore the IDisposable interface in .NET for a very long time. Many .NET programmers never call the Dispose() method on disposable objects and never use the using statement and their programs work just fine. The garbage collector keeps the program humming along, calling the finalizer on such classes to clean up.

But the Image and Bitmap classes are special. They are very thin managed classes wrappers around GDI+, an unmanaged api. Images can use lots of unmanaged memory to store the pixel data, many megabytes on large images. Combine that with a program that doesn't otherwise allocate enough managed objects to trigger a garbage collection and you've got a fat piggy problem.

You must dispose images after you are done using them to avoid this problem. That's a bit difficult to do when you use the PictureBox.ImageLocation property, the PictureBox class loads the image using a worker thread. It cannot itself dispose the previous image, it cannot know if the image might be used somewhere else. You have to help:

    foreach(string x in files)
    {
        string imgIndex = x.Remove(0,x.LastIndexOf("_")+1).Remove(1);
        PictureBox pic = pictureBox1; 
        //...
        if (pic.Image != null) pic.Image.Dispose();
        pic.Image = null;
        pic.ImageLocation = x;
    }

Or use the Image.FromFile() method instead so you don't have to look at the empty picture box.




回答2:


Perhaps UI virtualization can help you.

Do you want to show all those pictureboxes at once?

As I understood your question, you only want to show 8 of them at once.

Please have a look at the following article UI / Data virtualization

and especially the virtualizing panel




回答3:


Displaying the pictures is handled by the OS (the GDI subsystem), and this introduces a known memory inefficiency: The image is internally rendered to a bitmap in its original size, using a substantial amount of memory, this bitmap is then scaled down only for display.

Your best bet is to create small preview images and display those instead.

Also keep in mind, that you are working in a garbage collected environment: Not all the memory you see in Task Manager is really used, if memory pressure builds up the GC will more aggressivly return memory to the system - in fact your application is likely to use less memory if run on a system with less available memory.



来源:https://stackoverflow.com/questions/16495638/show-a-lot-of-images-with-really-low-memory-using-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!