سؤال

أنا نيوا في ج #. لا بد لي من تحديث مربع صورة واجهة المستخدم الرسومية بشكل متكرر في مؤشر ترابط عامل. يتم الحصول على الصورة من كاميرا اقتراع برنامج تشغيل مع طريقة GetSimage يسترجع الصورة المراد عرضها. حتى إذا قمت بتخصيص الصورة النقطية باستخدام التوجيه "باستخدام" وتدعو 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();

    }

في حين أن طريقة السحب هي شيء مثل

   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:

أنت مسؤول عن استدعاء أسلوب DeleteObject GDI لتحرير الذاكرة المستخدمة من قبل كائن NTMAP GDI.

ثم الطريقة من fromhbitmap تجعل نسخة من الصورة النقطية GDI؛ لذلك يمكنك إصدار الصورة النقطية GDI الواردة باستخدام طريقة DeleteObject GDI مباشرة بعد إنشاء الصورة الجديدة.

لذلك في الأساس أود أن أضيف:

[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 لأداء نوع من التحول. في حال كنت لا تستطيع فقط تعيين الصورة النقطية إلى خاصية الصورة الخاصة بك لصياغتك، وتجاهل الحل السابق:

// 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 bmp = new Bitmap(fileName);
pbox.Image = bmp; // notice that we used bitmap class to initialize pbox.

... ثم تريد إطلاق ملف الصورة bmp.Dispose();
الآن يمكنك حذف أو نقل أو ما تريد إلى الملف.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top