Member 13522501 Ответов: 3

Сообщение из памяти при чтении некоторых картинок из БД


Привет в моей таблице есть поле для хранения фотографий, оно работает хорошо и без проблем.
Но когда я читаю картинки из БД, то появляется сообщение “Out of Memory”.
Я думаю, что это командный файл.Flush() или File.Dispose() или File.Close() очистит буфер памяти, но эти команды ничего не сделают.
Код:

System.IO.FileStream File = new System.IO.FileStream("C:\\ TempFile\\" + PictureFileName_Field, System.IO.FileMode.Create, System.IO.FileAccess.Write);
            byte[] bytFile = new byte[File.Length + 1];
            
            bytFile = (byte[])(PictureFile_Field);
            File.Write(bytFile, 0, bytFile.Length - 1);

            File.Flush();
            File.Dispose();
            File.Close();


Язык c#, а БД-это sql server.
Большое спасибо

Что я уже пробовал:

Я не знаю, что мне делать.
.........................
спасибо

3 Ответов

Рейтинг:
2

Richard MacCutchan

То Flush и Close методы просто гарантируют, что все данные были записаны в файл правильно. Они ничего не меняют в памяти, ваш код должен удалить любые объекты, которые больше не требуются..

byte[] bytFile = new byte[File.Length + 1]; // a new array in memory - which you never use

bytFile = (byte[])(PictureFile_Field); // now set it to point to Picture_Field
File.Write(bytFile, 0, bytFile.Length - 1); // write the bytes to a new file

File.Flush();
File.Dispose();  // dispose the File object
File.Close();    // you cannot call Close on a disposed object
//
// but the PictureFile_Field still exists in memory, you need to delete it


Рейтинг:
2

OriginalGriff

Цитата:
... когда я прочитаю картинки из БД, появится сообщение “Out of Memory”.

Начните с того, как Вы читаете данные из БД:
Если вы используете
SELECT * FROM ...
Затем не перечисляйте свои поля, чтобы не возвращать больше данных, чем вам нужно.
Затем посмотрите, что вы используете для извлечения данных - если ваш код использует SqlDataAdapter для заполнения DataTable или DataSet, то это требует, чтобы SQL Server собрал все данные вместе и передал их в виде одного куска - изображения могут быть довольно большими, так что если их много, то это может перегрузить вашу систему или SQL server (и если вы работаете с локальной БД для разработки, помните, что это означает, что по крайней мере в два раза больше пространства данных требуется на одной машине). Попробуйте переключиться на DataReader, который возвращает строки по требованию, а не все сразу.
Затем посмотрите на количество строк, которые вы извлекаете: если только вы не используете WHERE пункт на вашем SQL вы получите все из них, так что вполне возможно, что вы получаете большое количество изображений, которые вам не нужны. Добавьте предложение WHERE или попробуйте возвращать данные на страницах по десять или двадцать, а не все сразу, что также должно уменьшить использование памяти.

И следите за монитором памяти в отладчике во время запуска вашего приложения - посмотрите, сколько оно на самом деле использует (ошибки"из памяти" вызваны не только нехваткой "реальной памяти" - вы также получаете его для ограниченных ресурсов, таких как дескрипторы и графические контексты, так что это может быть какая-то другая часть вашего кода, которая на самом деле вызывает проблему. Проверьте сведения об исключении в отладчике, чтобы попытаться найти дополнительную информацию.


Рейтинг:
0

MadMyche

Я обычно использую a using[^] блок, когда я использую расходный материал объекты.

Он не только заботится о самом одноразовом объекте, но и любые объекты, созданные в нем, будут выпадать из области видимости при закрытии блока, поэтому массив байтов может быть немедленно подобран сборщиком мусора.

Вы также можете упростить свой код, включив инструкцию link (using) для Sytem.IO в верхней части страницы, то вы можете удалить ссылки на него при вызове ссылок FileStream.

using System.IO.; // top of page
// prior code

using (FileStream File = new FileStream("C:\\ TempFile\\" + PictureFileName_Field, FileMode.Create, FileAccess.Write)) {

	byte[] bytFile = new byte[File.Length + 1];
	bytFile = (byte[])(PictureFile_Field);

	File.Write(bytFile, 0, bytFile.Length - 1);
	File.Flush();

	File.Close();   // some say not needed, but doesn't hurt anything so why not
	File.Dispose(); // can omit, not really needed when using a USING block
}
Рекомендации:
использование инструкции - Справочник по C# | Microsoft Docs[^]
Класс FileStream (System.IO) | Microsoft Docs[^]
c# - Как правильно распорядиться массивом байтов, используемым в классе? - переполнение стека[^]