[英]Why doesn't FastBitmap get garbage collected?
因此,我終於找到了內存消耗增加的問題。 這是下面的類,由於某種原因,該類未收集垃圾。 有什么問題嗎? FastBitmap類的想法是一次鎖定位圖圖像的位圖數據,以避免在每次調用GetPixel / SetPixel時鎖定/解鎖。
public unsafe class FastBitmap
{
private Bitmap subject;
private int subject_width;
private BitmapData bitmap_data = null;
private Byte* p_base = null;
public FastBitmap(Bitmap subject_bitmap)
{
this.subject = subject_bitmap;
try
{
LockBitmap();
}
catch (Exception ex)
{
throw ex;
}
}
public void Release()
{
try
{
UnlockBitmap();
}
catch (Exception ex)
{
throw ex;
}
}
public Bitmap Bitmap
{
get { return subject; }
}
public void LockBitmap()
{
GraphicsUnit unit = GraphicsUnit.Pixel;
RectangleF boundsF = subject.GetBounds(ref unit);
Rectangle bounds = new Rectangle((int)boundsF.X, (int)boundsF.Y, (int)boundsF.Width, (int)boundsF.Height);
subject_width = (int)boundsF.Width * sizeof(int);
if (subject_width % 4 != 0)
{
subject_width = 4 * (subject_width / 4 + 1);
}
bitmap_data = subject.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
p_base = (Byte*)bitmap_data.Scan0.ToPointer();
}
private void UnlockBitmap()
{
if (bitmap_data == null) return;
subject.UnlockBits(bitmap_data); bitmap_data = null; p_base = null;
}
}
編輯
這是如何正確收集它的方法。
public unsafe class FastBitmap : IDisposable
{
private Bitmap subject;
private int subject_width;
private BitmapData bitmap_data = null;
private Byte* p_base = null;
public FastBitmap(Bitmap subject_bitmap)
{
this.subject = subject_bitmap;
try
{
LockBitmap();
}
catch (Exception ex)
{
throw ex;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
UnlockBitmap();
Bitmap.Dispose();
}
subject = null;
bitmap_data = null;
p_base = null;
disposed = true;
}
}
~FastBitmap()
{
Dispose(false);
}
public Bitmap Bitmap
{
get { return subject; }
}
public void LockBitmap()
{
GraphicsUnit unit = GraphicsUnit.Pixel;
RectangleF boundsF = subject.GetBounds(ref unit);
Rectangle bounds = new Rectangle((int)boundsF.X, (int)boundsF.Y, (int)boundsF.Width, (int)boundsF.Height);
subject_width = (int)boundsF.Width * sizeof(int);
if (subject_width % 4 != 0)
{
subject_width = 4 * (subject_width / 4 + 1);
}
bitmap_data = subject.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
p_base = (Byte*)bitmap_data.Scan0.ToPointer();
}
public void UnlockBitmap()
{
if (bitmap_data == null) return;
subject.UnlockBits(bitmap_data); bitmap_data = null; p_base = null;
}
}
幾點:
您的班級擁有對固定數據的訪問權限。 垃圾收集器通過在內存中移動結構來工作。 只要位圖已鎖定其位,垃圾收集器就無法對其進行任何操作。
釋放FastBitmap后,恐怕GDI +可能仍然掛在數據位上。 GDI +是不與垃圾收集器進行交互的本機庫。
您還需要釋放(處理)GDI + Bitmap
。 只需在Release
調用subject.Dispose()
。
正如Mitchel所言,最好使FastBitmap實現IDisposable並重命名Release
以進行處理。 這將允許您在代碼中使用using語句,以確保確定性地釋放了數據。
乍一看,我想說的是您要研究在類上實現IDisposable接口,以便可以確保釋放出該類正在使用的資源。
如果未收集此類,則還有其他引用。 雖然內部數據可能會保持鎖定狀態,但我還是先來看其他地方。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.