проблема освобождения памяти c# picturebox

Я новичок в C#. Я должен неоднократно обновлять поле изображения GUI в рабочем потоке. Изображение, приобретенное с камеры избирательных водитель с метод getimage, что retrives изображение, которое будет отображаться. Даже если я выделяю растровое изображение с помощью директивы "using" и явно вызываю G. C, память, похоже, никогда не освобождается.

рабочий поток выглядит примерно так:

   while (true)
    {
        // request image with IR signal values (array of UInt16)
        image = axLVCam.GetImage(0);
        lut = axLVCam.GetLUT(1);
        DrawPicture(image, lut);
        //GC.Collect();

    }

в то время как метод DrawPicture-это что-то как

   public void DrawPicture(object image, object lut)
{

  [...]

    // We have an image - cast it to proper type
    System.UInt16[,] im = image as System.UInt16[,];
    float[] lutTempConversion = lut as float[];

    int lngWidthIrImage = im.GetLength(0);
    int lngHeightIrImage = im.GetLength(1);

    using (Bitmap bmp = new Bitmap(lngWidthIrImage, lngHeightIrImage)) {

      [...many operation on bitmap pixel...]

        // Bitmap is ready - update image control

        //SetControlPropertyThreadSafe(tempTxtBox, "Text", string.Format("{0:0.#}", lutTempConversion[im[160, 100]]));

        //tempTxtBox.Text = string.Format("{0:00000}", im[160, 100]);
        //System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
        pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
    }
}

проблемы возникают с

рис.система визуализации.Рисунок.Изображение.FromHbitmap(bmp.GetHbitmap ());

фактически комментируя эту строку кода, сборка мусора работает так, как она будет. Лучше, проблема, кажется, с

3 ответов


Image осуществляет IDisposable, Так что вы должны позвонить Dispose в каждом Image экземпляр, который вы создаете, когда он больше не нужен. Вы можете попытаться заменить эту строку в своем коде:

pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());

С этого:

if (pic.Image != null)
{
    pic.Image.Dispose();
}
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());

это будет утилизировать предыдущее изображение (если таковое имеется) перед назначением нового.


дело в том, что вы делаете растровое изображение GDI bmp С GetHbitmap, который согласно msdn:

вы несете ответственность за вызов Метод GDI DeleteObject для освобождения память, используемая растровым объектом GDI.

затем метод FromHbitmap создает копию растрового изображения GDI; таким образом, вы можете освободить входящее растровое изображение GDI с помощью метода GDI DeleteObject сразу после создания нового изображения.

Так что в основном я бы добавить:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

...

IntPtr gdiBitmap = bmp.GetHbitmap();

// Release the copied GDI bitmap
if (pic.Image != null)
{
    pic.Image.Dispose();
}

pic.Image = System.Drawing.Image.FromHbitmap(gdiBitmap);

// Release the current GDI bitmap
DeleteObject(gdiBitmap);

Я не уверен, что вам нужно растровое изображение GDI для выполнения какого-то преобразования. Если вы этого не сделаете, вы можете просто назначить растровое изображение свойству Image вашего PictureBox и игнорировать первое решение:

// Since we're not using unmanaged resources anymore, explicitly disposing 
// the Image only results in more immediate garbage collection, there wouldn't 
// actually be a memory leak if you forget to dispose.
if (pic.Image != null)
{
    pic.Image.Dispose();
}

pic.Image = bmp;

существует несколько способов освободить изображение из pbox. Я настоятельно рекомендую способ, что не используйте pbox.Image = Image.FromFile.... Если вы не используете FileStream и хотите прочитать его из файла, используйте класс BitMap. Вот так:

Bitmap bmp = new Bitmap(fileName);
pbox.Image = bmp; // notice that we used bitmap class to initialize pbox.

... и тогда вы хотите, чтобы освободить файл изображения bmp.Dispose();
Теперь вы можете удалить, переместить или все, что вы хотите в файл.