C#Picturebox内存泄漏

时间:2013-03-21 09:52:10

标签: c# .net aforge

我查看了几页类似的查询,实现了大部分建议,但似乎找不到任何有效的方法。希望我不会忽视一些明显的东西。

是的,所以我正在使用AForge.net来捕捉图像。它提供了一个事件,该事件是为每个收到的新帧触发的,在我的代码中如下所示:

private void videoSourcePlayer_NewFrame(object sender, ref Bitmap image)
    {
        framesRecieved++;
        try
        {
            if (!stopCapturing)
            {
                if (pictureBox1.Image != null)
                {
                    pictureBox1.Image.Dispose();
                }
                pictureBox1.Image = image.Clone(new Rectangle(0, 0, image.Width, image.Height), image.PixelFormat);
            }

        }
        catch { }
        finally { GC.Collect(); }
    }

只要窗口保持静止,内存使用率就非常稳定,但只要我抓住窗口并开始移动它,内存使用率就会持续上升。我之所以被认为可能与图片框有关,是因为只要我将“stopCapturing”bool变为true,即使我在窗口周围移动窗口,内存也会停止上升。 “stopCapturing”不用于其他任何事情,并且事件继续正常触发,唯一的区别是图片显示在图片框中。我对原因感到茫然,所以任何帮助都会受到赞赏。

PS:不确定它是否相关,但我的工作站有2个屏幕。

2 个答案:

答案 0 :(得分:0)

Bitmap.Clone()执行浅拷贝,实际字节仍然由调用者拥有,因此这可能会导致各种麻烦。 你需要做一个深层复制。

例如,AForge way

Bitmap bmp = AForge.Imaging.Image.Clone(image);

或者GDI +方式(也可以使用lockbits等来获得更好的性能):

Bitmap bmp = new Bitmap(image.Width, image.Height, image.PixelFormat);
Graphics g = Graphics.FromImage(bmp);
g.DrawImageUnscaled(image, Point.Empty);

答案 1 :(得分:0)

我想知道为什么你要克隆图像。令我感到震惊的是,当pictureBox1.Image为null或图像的尺寸或像素格式发生变化时,您应该只分配一个新图像:

private bool BitmapChanged(Bitmap old, Bitmap new)
{
    return old == null || old.PixelFormat != new.PixelFormat ||
        old.Width != new.Width || old.Height != new.Height;
}

private Bitmap MakeSimilarBitmap(Bitmap source)
{
    Bitmap copy = new Bitmap(source.Width, source.Height, source.PixelFormat);
    return copy;
}

private void DrawOnto(Image im, Bitmap source)
{
    using (Graphics g = Graphics.FromImage(im)) {
        g.DrawImage(source, 0, 0);
    }
}

然后当你得到一个框架时,你会做这样的事情:

Image im = BitmapChanged(pictureBox1.Image as Bitmap, srcBmp) ?
                          MakeSimilarBitmap(image) : pictureBox1.Image;
DrawOnto(im, srcBmp);
bool same = im == pictureBox1.Image;
if (same)
    pictureBox1.Invalidate();
else {
    Image old = pictureBox1.Image;
    pictureBox1.Image = im;
    old.Dispose();
}