Я пытаюсь разработать Windows Mobile 6 (в WF/C#) приложение. Существует только одна форма и на форме существует только объект PictureBox. На нем я привлекаю все желаемые средства управления или независимо от того, что я хочу.
Существует две вещи, которые я делаю. Рисование пользовательских форм и загрузка битовых массивов из .png файлов.
Следующая строка блокирует файл при загрузке (который является нежелательным сценарием):
Bitmap bmp = new Bitmap("file.png");
Таким образом, я использую другой способ загрузить битовый массив.
public static Bitmap LoadBitmap(string path) {
using (Bitmap original = new Bitmap(path))
{
return new Bitmap(original);
}
}
Это, я предполагаю намного медленнее, но я не знаю лучшего способа загрузить изображение, быстро выпущение файла блокирует.
Теперь, при рисовании изображения существует метод, который я использую:
public void Draw() {
Bitmap bmp = new Bitmap(240,320);
Graphics g = Graphics.FromImage(bmp);
// draw something with Graphics here.
g.Clear(Color.Black);
g.DrawImage(Images.CloseIcon, 16, 48);
g.DrawImage(Images.RefreshIcon, 46, 48);
g.FillRectangle(new SolidBrush(Color.Black), 0, 100, 240, 103);
pictureBox.Image = bmp;
}
Это однако, кажется, некоторая утечка памяти. И если я продолжаю делать его слишком долго, приложение в конечном счете отказывает.
Поэтому у меня есть 3 вопроса:
1.) Каков лучший путь к загрузке битовых массивов из файлов, не блокируя файл?
2.) Что возражает потребностям, которые будут вручную расположены в Ничьей () функция (и в который порядок), таким образом, нет никакой утечки памяти и никакого броска ObjectDisposedException?
3.) Если поле изображения. Изображение установлено на bmp, как в последней строке кода, был бы поле изображения. Изображение. Расположите (), располагают только ресурсы, связанные с поддержанием поля изображения. Изображение или базовый Растровый набор к нему?
1: Я не знаю, работает ли это в Windows Mobile, но попробуйте следующее:
FileStream bitmapFile = new FileStream("mybitmap.bmp", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Image loaded = new Bitmap(bitmapFile);
2: SolidBrush
должен быть утилизирован. Есть общее правило утилизации. -> «каждый созданный вами объект, который реализует утилизацию, должен быть удален вручную, за исключением случая, когда объект является значением возврата / ссылки / выхода»
В этом случае лучше использовать using
statement
using (new objecttodispose){ ..... }
Оператор using
обеспечит вызов Dispose ()
в любом случае (например, исключение).
3: Dispose ()
освободит ресурсы растровых изображений.
Я не думаю, что существует реальная утечка памяти . Проблема в том, что вы не удаляете старое растровое изображение, его должен очистить сборщик мусора. Но нет детерминированного способа сказать , когда это произойдет.
Я думаю, что если вы собираетесь перебрать много изображений, вы увидите некоторое увеличение памяти, а в какой-то другой момент она упадет или будет сопротивляться в одном месте.
Я не тестировал его, но, возможно, это немного поможет сделать его более детерминированным:
public void Draw() {
Bitmap bmp = new Bitmap(240,320);
using(var g = Graphics.FromImage(bmp))
using(var solidBrush = SolidBrush(Color.Black))
{
// draw something with Graphics here.
g.Clear(Color.Black);
g.DrawImage(Images.CloseIcon, 16, 48);
g.DrawImage(Images.RefreshIcon, 46, 48);
g.FillRectangle(solidBrush, 0, 100, 240, 103);
//Backup old image in pictureBox
var oldImage = pictureBox.Image;
pictureBox.Image = bmp;
//Release resources from old image
if(oldImage != null)
((IDisposable)oldImage).Dispose();
}
}
И еще одна идея, вдохновленная jack30lena:
public static Bitmap LoadBitmap(string path)
{
//Open file in read only mode
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
//Get a binary reader for the file stream
using (BinaryReader reader = new BinaryReader(stream))
{
//copy the content of the file into a memory stream
var memoryStream = new MemoryStream(reader.ReadBytes((int)stream.Length));
//make a new Bitmap object the owner of the MemoryStream
return new Bitmap(memoryStream);
}
}
Идея моего второго примера кода состоит в том, чтобы получить избавиться от дескриптора файла и скопировать содержимое файла в память. Впоследствии Bitmap станет владельцем MemoryStream, который будет удален в моем первом образце путем вызова oldImage.Dispose ()
.
При использовании этого подхода в памяти никогда не должно быть более двух изображений, тысячи из которых приводят только к OutOfMemoryExceptions из-за действительно больших изображений или небольшого объема ОЗУ.