簡體   English   中英

為什么FastBitmap不收集垃圾?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM