загрузить 1000 изображений в c # без исключения нехватки памяти - PullRequest
3 голосов
/ 24 января 2012

Я хочу добавить 1000 изображений (каждый размер (от 40 до 100) КБ) на панели во время выполнения в настольном приложении.Сначала пользователь просматривает все изображения и загружает их на панель.Когда он загружает изображения один за другим, использование памяти, показанное в диспетчере задач, быстро увеличивается, и после определенного количества изображений отображается «Исключение нехватки памяти».Где ошибка в моем коде?

Перед загрузкой диспетчера задач 700 изображений показывает 1,05 ГБ использование памяти.После загрузки диспетчер задач показывает 2,04 ГБ и 2 ГБ переполнения ОЗУ

int picnumber = 0;
        int numberOfImages = 12;

        numberOfImages = Convert.ToInt32(textBox1.Text.ToString());

        for (int i = 0; i < numberOfImages; i++)
        {
            GroupBox gBox = new GroupBox();

            picnumber++;


            ////////////////////////////////

            // calculate the position of the groupbox where it is placed.
            if ((picnumber % 3) == 1)
            {
                x = initX;
            }
            else
            {
                if ((picnumber % 3) == 0)
                {
                    x = initX + 2 * (130 + 20);
                }
                else
                {
                    x = initX + 130 + 20;
                }

            }
            ///////////////////////////////////


            System.Drawing.Point CurrentPoint;

            CurrentPoint = panel1.AutoScrollPosition;
            y = initY + ((picnumber - 1) / 3) * (130 + 20) - (Math.Abs(panel1.AutoScrollPosition.Y));

            gBox.Text = picnumber.ToString();

            //place the groupbox in the appropriate position.
            gBox.Location = new System.Drawing.Point(x, y);
            gBox.Size = new System.Drawing.Size(130, 130);

            Bitmap btmap = new Bitmap(@"E:\43.jpg");
            // attach the image to the groupbox
            gBox.BackgroundImage = btmap;
            **gBox.BackgroundImageLayout = ImageLayout.Stretch;
            // add the groupbox that contains image to the panel.
            panel1.Controls.Add(gBox);**

Но я видел некоторые приложения, которые могут загружать огромное количество изображений и занимают незначительную память,например, «Batch Image Resizer» (http://www.jklnsoft.com/)

Как приложение обрабатывает память? Какой механизм они используют?

Перед загрузкой диспетчера задач 700 изображенийпоказывает использование памяти 1,05 ГБ. После загрузки диспетчер задач показывает 1,06 ГБ

Среда разработки: C # .net Framework 4, Windows XP, Visual Studio 2010, ОЗУ: 2 ГБ

Ответы [ 4 ]

7 голосов
/ 24 января 2012

Важно отметить, что JPG размером 100 КБ займет лот больше памяти, чем просто 100 КБ. 100 КБ - сжатый размер данных на диске. Если у вас есть 32-битное (что означает 4 байта на пиксель информации об изображении) изображение размером 800x600, оно может быть размером 100 КБ на диске, но вы распаковываете его и сохраняете в памяти, чтобы его можно было отобразить, это 800 * 600 *. 4 = 1 920 000 байт = 1,83 МБ ОЗУ. 1.83 * 700 = 1 281 МБ ОЗУ для хранения всех этих изображений.

Решение состоит в том, чтобы загрузить изображение и создать его уменьшенный эскиз в памяти, а затем удалить исходное изображение из памяти. Если ваш 800x600 имеет миниатюру размером 80x60 @ 16 бит, то для отображения требуется всего 9,3 КБ ОЗУ. 700 из них потребляют только 6,5 МБ ОЗУ - огромная разница!

5 голосов
/ 24 января 2012

Вы, вероятно, хотите загрузить их по требованию и кэшировать их. Это означает, что если у вас есть, скажем, 20 фотографий, видимых в вашем окне, вы можете загрузить 40 фотографий - 10 до текущей позиции, 20 видимых фотографий и 10 после текущей позиции. По мере того, как пользователь прокручивает, вы можете выбросить все, что прокрутилось после начальной позиции, и прочитать те, которые появятся в ближайшее время. Таким образом, у вас в памяти останется только несколько слов, а вы читаете только несколько больше.

3 голосов
/ 24 января 2012

Вы должны распоряжаться ресурсами, такими как растровые изображения, после того, как вы их использовали. Вы можете сделать это с помощью:

using(Bitmap btmap = new Bitmap("E:\etc...")) {
   ... code here
}

Но делайте это с каждой итерацией, а не после того, как вы перебрали все свои ресурсы!

0 голосов
/ 07 августа 2015

Используйте CacheOption для него.

public static ImageSource BitmapFromUri(Uri source)
{
    var bitmap = new BitmapImage();
    bitmap.BeginInit();
    bitmap.UriSource = source;
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.EndInit();
    return bitmap;
}
...