2013-04-09 53 views
2

我正在用C#开发一个应用程序,并且我开发了一个用Aforge相机完成一些内容的库。其中一点是简单地捕捉到了什么是在网络摄像头前的图像,并显示在一个特定的PictureBox这样做:AForge相机内存泄漏

camera.NewFrame += NewFrame; 

private void NewFrame(object sender, NewFrameEventArgs args) 
    { 
     Bitmap newFrame = new Bitmap(args.Frame); 
     args.Frame.Dispose(); 
     PictureBox.FromBitmapImage(newFrame); 
     newFrame.Dispose(); 
     newFrame = null; 
    } 

我做什么在这里,我得到的每一个帧,并将其绘制成PictureBox

我的疑问是:

在某些计算机,绘画这种方式产生了非常高的内存泄漏。相机配置为:640x480,如果更高,内存泄漏会增加。

计算机配置:

英特尔I5:内存泄漏为500MB

英特尔I7: NO内存泄漏。

双coeur(不那么强大):没有那么多的内存泄漏。

编辑:

public static void FromBitmapImage(this Image image, Bitmap bitmap) 
    { 
     BitmapImage bitmapImage = new BitmapImage(); 

     using (MemoryStream memoryStream = new MemoryStream()) 
     { 
      bitmap.Save(memoryStream, ImageFormat.Bmp); 
      memoryStream.Position = 0; 
      bitmapImage.BeginInit(); 
      bitmapImage.StreamSource = memoryStream; 
      bitmapImage.CacheOption = BitmapCacheOption.OnLoad; 
      bitmapImage.EndInit(); 
     } 

     image.Source = bitmapImage; 
     bitmapImage = null; 
    } 

我不明白为什么我有一些电脑和其他人没有内存泄漏...任何建议吗?

注意:内存泄漏只发生在Visual Studio 2010上的发布模式下,而不是在调试时发生。

NOTE2:我认为问题自带FromBimapImage,因为我尝试了WindowsForms应用程序而不是一个WPF并没有内存泄漏......

+0

什么是'PictureBox.FromBitmapImage(位图)'方法,它返回什么? – 2013-04-09 14:22:21

回答

3

AForge owns图像的字节,你应该做你自己的副本。将框架传递给位图构造函数是不够的。如果框架无法正确处理位图,因为您有参考,则会出现泄漏。

试试这个:

private void NewFrame(object sender, NewFrameEventArgs args) 
{ 
    Bitmap newFrame = AForge.Imaging.Image.Clone(args.Frame); 
    PictureBox.FromBitmapImage(newFrame); 
    newFrame.Dispose(); 
} 
+0

我用这种方式,但我仍然有一些内存泄漏。我意识到,只有当我在Visual Studio 2010上发布时,内存泄漏才存在。任何想法为什么? – Sonhja 2013-04-10 08:10:20

+0

你的解决方案是问题的一部分,但我也不得不'冻结'内存流方法中的'BitmapImage' :)解决! – Sonhja 2013-04-10 15:48:09

2

这对我的作品。

 if (pictureBox1.Image != null) { 
      pictureBox1.Image.Dispose(); 
     } 
     Bitmap bitmap = eventArgs.Frame.Clone() as Bitmap; 
     pictureBox1.Image = bitmap; 
0

处置图片框图像右侧前分配新的工作,以防止内存泄漏,但是当我调整了图片框扔错误。这个问题可能是由于处理图像太快造成的。它对我的工作原理是将旧图像保存在一个队列中,并将它们延迟5个图像。这会让图片有足够的时间赶上。

private Queue<Image> _oldImages = new Queue<Image>(); 
... 

if (pictureBox1.Image != null) 
{ 
    _oldImages.Enqueue(pictureBox1.Image); 
    if (_oldImages.Count > 5) 
    { 
    var oldest = _oldImages.Dequeue(); 
    oldest.Dispose(); 
    } 
}