[英]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.