Недостаточно памяти, несколько изображений в одном PictureBox
-
20-09-2019 - |
Вопрос
У меня возникла проблема с нехваткой памяти, когда я пытаюсь загрузить несколько изображений в один PictureBox.
public void button2_Click(object sender, EventArgs e)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
dialog.ShowDialog();
string selected = dialog.SelectedPath;
string[] imageFileList = Directory.GetFiles(selected);
int iCtr = 0,zCtr = 0;
foreach(string imageFile in imageFileList)
{
if (Image.FromFile(imageFile) != null)
{
Image.FromFile(imageFile).Dispose();
}
PictureBox eachPictureBox = new PictureBox();
eachPictureBox.Size = new Size(100,100);
// if (iCtr % 8 == 0)
//{
// zCtr++;
// iCtr = 0;
//}
eachPictureBox.Location = new Point(iCtr * 100 + 1, 1);
eachPictureBox.Image = Image.FromFile(imageFile);
iCtr++;
panel1.Controls.Add(eachPictureBox);
}
}`enter code here`
Решение
if (Image.FromFile(imageFile) != null) { Image.FromFile(imageFile).Dispose(); }
Плохой.Вы загружаете изображение из файла, проверяете, является ли результат нулевым... затем снова загружаете его в новый результат, чтобы можно было его удалить.Хотя последняя часть глупа, она не вредна.Однако первая часть является результатом Image
никогда не удаляется должным образом (если/когда сборщик мусора собирает его, финализатор на Image
тип должен избавьтесь от неуправляемых ресурсов, но полагаться на это неразумно).
Кстати, Image.FromFile
никогда не вернется null
.Если он не может прочитать изображение, он выдаст ошибку OutOfMemoryException
.
Код также ничего не делает, поскольку нет else
блок и ничего значимого не делается в if
блокировать.
Я предполагаю, что ваш OutOfMemoryException
происходит из-за того, что один или несколько файлов в этом каталоге хранятся в поврежденном или неподдерживаемом формате изображения., или вообще не является изображением.
Попробуйте заменить код в вашем foreach
с этим:
try
{
Image image = Image.FromFile(imageFile);
PictureBox eachPictureBox = new PictureBox();
eachPictureBox.Size = new Size(100,100);
eachPictureBox.Location = new Point(iCtr * 100 + 1, 1);
eachPictureBox.Image = Image.FromFile(imageFile);
iCtr++;
panel1.Controls.Add(eachPictureBox);
}
catch(OutOfMemoryException) { } // skip the file
Другие советы
Внутри поля изображения содержится ссылка на растровое изображение, которое вы в него помещаете.Если вы не избавитесь от поля изображения, оно будет содержать ссылку на каждое растровое изображение, которое вы в него загружаете.
Следует учитывать, что независимо от типа изображения, хранящегося на диске, когда вы открываете его для отображения, изображение становится растровым и требует 4 байта на отображаемый пиксель.
Кажется, ваш код предполагает попытку операции с миниатюрами.Вы по факту загружаете в память 70 файлов и независимо от размера дисплея, в памяти они будут очень большими.
Например, предположим, что у вас есть 70 изображений в формате JPEG с глубиной цвета 32 бита и размером, скажем, 1920x1080 пикселей.Ваши требования к памяти для одновременной загрузки такого количества изображений составляют:
70 pics x 1920 pixels x 1080 pixels x 4 bytes/pixel = 580,608,000 bytes!
И это довольно заниженная оценка.
Вы могли бы рассмотреть возможность загрузки гораздо меньшего количества изображений или попробовать настоящее решение для создания миниатюр.