Правильный способ расположить Изображение/Битовый массив и PictureBox

Я пытаюсь разработать 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, как в последней строке кода, был бы поле изображения. Изображение. Расположите (), располагают только ресурсы, связанные с поддержанием поля изображения. Изображение или базовый Растровый набор к нему?

23
задан Kornelije Petak 11 May 2010 в 07:21
поделиться

2 ответа

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 () освободит ресурсы растровых изображений.

7
ответ дан 29 November 2019 в 02:57
поделиться

Я не думаю, что существует реальная утечка памяти . Проблема в том, что вы не удаляете старое растровое изображение, его должен очистить сборщик мусора. Но нет детерминированного способа сказать , когда это произойдет.

Я думаю, что если вы собираетесь перебрать много изображений, вы увидите некоторое увеличение памяти, а в какой-то другой момент она упадет или будет сопротивляться в одном месте.

Я не тестировал его, но, возможно, это немного поможет сделать его более детерминированным:

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 из-за действительно больших изображений или небольшого объема ОЗУ.

13
ответ дан 29 November 2019 в 02:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: