2013-03-21 133 views
0

我已经浏览了几页类似的查询,实现了大部分建议,但似乎无法找到迄今为止工作的任何内容。希望我没有忽略明显的东西。C#Picturebox内存泄漏

对,所以我使用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(); } 
    } 

内存使用情况非常稳定,只要窗口保持静止,但只要我抓住窗口形式并开始移动它,内存使用量不断增加。我之所以被认为可能与picturebox有关,是因为只要我将“stopCapturing”布尔变为true,即使我在屏幕上移动窗口,内存也会停止上升。 “stopCapturing”不用于其他任何事情,并且事件继续正常触发,唯一的区别是正在显示在图片框中的图像。我对这个原因感到茫然,所以任何帮助将不胜感激。

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

+0

首先删除空捕获和GC.Collect。 – 2013-03-21 10:01:34

+1

不确定是否需要克隆。我以前使用过'新的位图(图片)'没有问题。 – 2013-03-21 12:52:08

回答

0

Bitmap.Clone()做一个浅拷贝,实际的字节仍然由调用者拥有,所以这可能会导致所有类型的麻烦。 您需要进行深层复制。

例如,AForge way

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

还是GDI +的方式(也可以使用lockbits等,为更好perfs):我不知道为什么你克隆

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

所有的图像。这让我感到当任pictureBox1.Image为空或只应分配一个新的图像时,图像变化的尺寸或像素格式:

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(); 
} 
+0

您需要制作副本,因为图像归VideoSource所有。它将自行处理。另请参见:http://www.aforgenet.com/framework/docs/html/63e8ac47-e9c1-d257-c587-c995c5a99b3f.htm – 2013-03-22 09:57:50

+0

我的观点是,您将内容复制到单个保留位图中,而不是分配新副本每一帧。 – plinth 2013-03-22 17:31:36