c # picturebox Speicherproblem freisetz
-
11-09-2019 - |
Frage
Ich bin ein Newby in C #. Ich muss immer wieder ein GUI-Bildfeld in einem Worker-Thread aktualisieren. Das Bild wird von einer Kamera Polling ein Fahrer mit einem GetImage Verfahren erworben, die das Bild retrives angezeigt werden. Selbst wenn ich die Bitmap-using-Direktive „using“ und explizit aufrufen G.C zuweisen, scheint Speicher nie freigegeben werden.
Der Worker-Thread ist so etwas wie folgt aus:
while (true)
{
// request image with IR signal values (array of UInt16)
image = axLVCam.GetImage(0);
lut = axLVCam.GetLUT(1);
DrawPicture(image, lut);
//GC.Collect();
}
Während die DrawPicture Methode ist so etwas wie
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());
}
}
Probleme stellen sich mit dem
pic.Image = System.Drawing.Image.FromHbitmap (bmp.GetHbitmap ());
In der Tat, dass die Code-Zeile zu kommentieren, Müllabfuhr funktioniert, wie es tun würde. Besser, das Problem scheint zu sein
System.Drawing.Image.FromHbitmap (bmp.GetHbitmap ())
Jede Beratung dieses Speicherleck zu lösen?
Vielen Dank!
Lösung
Image
implementiert IDisposable
, so dass Sie Dispose
auf jeder Image
Instanz aufrufen sollte, dass Sie erstellen, wenn es nicht mehr benötigt wird. Sie könnten versuchen, diese Zeile im Code zu ersetzen:
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
Mit diesem:
if (pic.Image != null)
{
pic.Image.Dispose();
}
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
Dies wird das vorherige Bild (falls vorhanden), bevor die neuen entsorgen zugeordnet ist.
Andere Tipps
Die Sache ist, sind Sie ein GDI-Bitmap von bmp
mit GetHbitmap machen, die nach Msdn:
Sie sind verantwortlich für den Aufruf der GDI DeleteObject Verfahren die frei Speicher, der von dem Objekt GDI-Bitmap verwendet wird.
Dann wird die FromHbitmap Methode macht eine Kopie der GDI-Bitmap; so können Sie die eingehende GDI-Bitmap lassen Sie die GDI DeleteObject-Methode unmittelbar nach dem neuen Image zu schaffen.
Also im Grunde möchte ich hinzufügen:
[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);
Ich bin nicht sicher, ob Sie den GDI-Bitmap eine Art von Transformation durchzuführen. Falls Sie Sie nicht nur ordnen Sie die Bitmap in die Bild-Eigenschaft des PictureBox kann, und ignorieren die frühere Lösung:
// 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;
Es gibt mehrere Möglichkeiten, um ein Bild von pbox zu lösen. Ich empfehle dringend, die Art und Weise, dass nicht verwendet pbox.Image = Image.FromFile...
ist. Wenn Sie Filestream nicht und Sie wollen es lesen, die aus der Benutzung BitMap Klassendatei. Wie folgt aus:
Bitmap bmp = new Bitmap(fileName);
pbox.Image = bmp; // notice that we used bitmap class to initialize pbox.
... und dann wollen Sie die Bilddatei bmp.Dispose();
freizugeben
Jetzt können Sie löschen, verschieben oder was auch immer Sie wollen in die Datei.