【发布时间】:2018-04-27 08:53:39
【问题描述】:
我正在制作一个小型应用程序,它以 Windows 形式显示实时网络摄像头提要,并且还存储带水印的图像以按指定时间间隔驱动(最终目标是创建延时视频)。
我正在使用 AForge 库进行图像和视频处理。
我有问题似乎存在内存泄漏,即使我尝试确保在每个进行图像处理的位置都使用“使用”语句。
以下是图像处理发生的代码(NewFrame 事件)
private void Video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
try
{
if (ImageProcessing) // If the previous frame is not done processing, let this one go
return;
else
ImageProcessing = true;
using (Bitmap frame = (Bitmap)eventArgs.Frame)
{
// Update the GUI picturebox to show live webcam feed
Invoke((Action)(() =>
{
webcam_PictureBox.Image = (Bitmap)frame.Clone();
}));
// During tests, store images to drive at a certain interval
if (ImageStoreTimer.Elapsed.TotalSeconds > ImageStoreTime)
{
DateTime dt = DateTime.Now;
using (Graphics graphics = Graphics.FromImage(frame))
{
PointF firstLocation = new PointF(frame.Width / 2, frame.Height / 72);
PointF secondLocation = new PointF(frame.Width / 2, frame.Height / 15);
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment = StringAlignment.Center;
using (Font arialFont = new Font("Arial", 15))
{
graphics.DrawString(dt.ToString(), arialFont, Brushes.Red, firstLocation, drawFormat);
graphics.DrawString(Pressure.ToString("F0") + " mbar", arialFont, Brushes.Red, secondLocation, drawFormat);
}
}
// Place images in a folder with the same name as the test
string filePath = Application.StartupPath + "\\" + TestName + "\\";
// Name images by number 1....N
string fileName = (Directory.GetFiles(filePath).Length + 1).ToString() + ".jpeg";
frame.Save(filePath + fileName, ImageFormat.Jpeg);
ImageStoreTimer.Restart();
}
}
//GC.Collect(); <----- I dont want this
}
catch
{
if (ProgramClosing == true){}
// Empty catch for exceptions caused by the program being closed incorrectly
else
throw;
}
finally
{
ImageProcessing = false;
}
}
现在,在运行程序时,我看到内存使用率上升和下降,通常在下降之前达到大约 900MB。但偶尔它会上升到 2GB。有时,我什至会在这一行遇到内存不足的异常:
Graphics graphics = Graphics.FromImage(frame)
所以在花了一个小时左右试图重塑代码并寻找我的内存泄漏之后,我终于尝试了代码中注释掉的 GC.Collect 行(耻辱)。之后,我的内存使用量保持不变,小于 60MB。而且我可以运行程序 24 小时没有任何问题。
所以我读了一些关于 GC.Collect 的内容,以及它有多糟糕,例如在程序中经常需要大量的处理能力才能做到这一点。但是当我比较我的程序使用的 CPU 功率时,无论我注释掉还是留下它,它都不会真正改变。但是如果我在新帧事件结束时收集,内存问题就消失了。
我想找到一个不涉及 GC.collect 函数的问题的解决方案,因为我知道这是不好的编程习惯,我应该找到潜在的问题根源。
提前谢谢大家!
【问题讨论】:
-
是的,GC 不好。重用一个对象总是比创建新对象更好,这对我解决内存问题有很大帮助,并且对性能更好
-
你试过注释掉“store-image”块吗?只是为了确保它不是问题的根源
-
如果您正在处理大量垃圾,那么当您了解第 1 代和第 2 代中可能存在的内容的性质时调用垃圾收集可能很有用,并且在某些情况下是必要的。是的,GC 可能会影响性能,因此您需要了解它,并且不要试图用错误的工具来填补糟糕的设计。一般来说,100 个涉及 GC.collect 的问题中有 98 个通常是内存泄漏的结果。虽然只是说应该不惜一切代价避免这些电话,而且是不好的,但过于简单化了一点
标签: c# .net winforms garbage-collection aforge