Вопрос

Я новичок в C#.Мне приходится неоднократно обновлять окно изображения графического интерфейса в рабочем потоке.Изображение получается с камеры, опрашивающей драйвер с помощью метода GetImage, который извлекает изображение для отображения.Даже если я выделю растровое изображение с помощью директивы using и явно вызову GC, память, похоже, никогда не будет освобождена.

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

   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());
    }
}

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

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

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

System.Drawing.Image.FromHbitmap(bmp.GetHbitmap())

Есть какие-нибудь советы по устранению этой утечки памяти?

Большое спасибо!

Это было полезно?

Решение

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, чтобы освободить память, используемую объектом Bitmap 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();
Теперь вы можете удалить, переместить или сделать что угодно в файле.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top