Continuous creation of bitmaps leads to memory lea

2020-03-16 07:11发布

问题:

I have a thread that continuously generates bitmaps and takes a screenshot of another program's window. Now, I have a pictureBox on my form, and that's constantly being updated with the bitmaps generated. Here's the code I have in the thread:

        Bitmap bitmap = null;

        while (true)
        {
            if (listBoxIndex != -1)
            {
                Rectangle rect = windowRects[listBoxIndex];
                bitmap = new Bitmap(rect.Width, rect.Height);
                Graphics g = Graphics.FromImage(bitmap);
                IntPtr hdc = g.GetHdc();
                PrintWindow(windows[listBoxIndex], hdc, 0);
                pictureBox1.Image = bitmap;
                g.ReleaseHdc(hdc);
            }
        }

As you can see, this leads to a memory leak, because of the continuous call to new Bitmap(rect.Width, rect.Height). I've tried adding "bitmap.Dispose()" to the bottom of the while loop, but that leads to the pictureBox's image also being disposed, which makes a giant red X in place of the actual image. Is there any way I can dispose of "bitmap" without disposing of the pictureBox image?

回答1:

You're also "leaking" the Graphics object. Try this:

    while (true)
    {
        if (listBoxIndex != -1)
        {
            Rectangle rect = windowRects[listBoxIndex];
            Bitmap bitmap = new Bitmap(rect.Width, rect.Height);
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                IntPtr hdc = g.GetHdc();
                try
                {
                    PrintWindow(windows[listBoxIndex], hdc, 0);
                }
                finally
                {
                    g.ReleaseHdc(hdc);
                }
            }
            if (pictureBox1.Image != null)
            {
                pictureBox1.Image.Dispose();
            }
            pictureBox1.Image = bitmap;
        }
    }


回答2:

The answered example has a leak with Graphics g after g.ReleaseHdc(..);

Remember to dipose the graphics variable

as for example:

g.Dispose();