Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 图像处理循环中的内存异常(需要比GC.collect更好的解决方案)_C#_.net_Winforms_Garbage Collection_Aforge - Fatal编程技术网

C# 图像处理循环中的内存异常(需要比GC.collect更好的解决方案)

C# 图像处理循环中的内存异常(需要比GC.collect更好的解决方案),c#,.net,winforms,garbage-collection,aforge,C#,.net,Winforms,Garbage Collection,Aforge,我正在制作一个小应用程序,它以windows窗体显示实时网络摄像头提要,并且还存储水印图像,以便在指定的时间间隔内驾驶(最终目标是创建timelapse视频) 我正在使用AForge库进行图像和视频处理 我遇到的问题似乎是内存泄漏,即使我试图确保在图像处理发生的每个位置都使用“using”语句 下面是图像处理发生时的代码(NewFrame事件) 因此,在花了一个小时左右的时间试图修改代码并查找内存泄漏后,我终于尝试了在代码中注释掉的GC.Collect行(羞耻)。之后,我的内存使用量保持不变,小

我正在制作一个小应用程序,它以windows窗体显示实时网络摄像头提要,并且还存储水印图像,以便在指定的时间间隔内驾驶(最终目标是创建timelapse视频)

我正在使用AForge库进行图像和视频处理

我遇到的问题似乎是内存泄漏,即使我试图确保在图像处理发生的每个位置都使用“using”语句

下面是图像处理发生时的代码(NewFrame事件)

因此,在花了一个小时左右的时间试图修改代码并查找内存泄漏后,我终于尝试了在代码中注释掉的GC.Collect行(羞耻)。之后,我的内存使用量保持不变,小于60MB。我可以运行程序24小时而没有任何问题

所以我读了一些关于GC.Collect的内容,以及它有多糟糕,例如,在程序中经常使用它可能需要大量的处理能力。但是,当我比较我的程序所使用的CPU能力时,不管我是否注释掉这一行,它都不会真正改变。但是如果我在新帧事件结束时收集,内存问题就消失了

我想找到一个不涉及GC.collect函数的问题解决方案,因为我知道这是一种糟糕的编程实践,我应该找到潜在的问题源


提前谢谢大家

我不擅长win表单,但我认为这一行:

Graphics graphics = Graphics.FromImage(frame)
webcam_PictureBox.Image = (Bitmap)frame.Clone();
将使前一个图像保持未经处理,这会泄漏内存(位图保留的非托管内存)。由于位图具有终结器-它将在将来某个时间由GC回收(或者当您调用
GC.Collect
),但正如您已经了解的那样-在这种情况下依赖GC不是一个好的做法。所以试着这样做:

if (webcam_PictureBox.Image != null)
    webcam_PictureBox.Image.Dispose();
webcam_PictureBox.Image = (Bitmap)frame.Clone();
Larse的合理评论:最好不要在图像仍被分配给
PictureBox.image
时处理它,因为谁知道呢,在分配新图像时,
PictureBox
控件可能会对旧图像执行任何操作。因此,备选方案是:

var oldImage = webcam_PictureBox.Image;
webcam_PictureBox.Image = (Bitmap)frame.Clone();
if (oldImage != null)
    oldImage.Dispose();

是的,GC不好。它总是更好地重用一个对象,而不是创建一个新的对象,这对我解决内存问题有很大帮助,并且对性能有更好的影响,您是否尝试过注释“存储图像”块?只是为了确保它不是问题的根源如果您处理大量垃圾,那么当您了解gen 1和gen 2中可能存在的内容的性质时,调用垃圾收集可能是有用的,并且在某些情况下是必需的。是的,GC可能会影响性能,所以您需要理解它,也不要试图用错误的工具来堵塞糟糕的设计。一般来说,100个涉及GC.collect的问题中有98个通常是内存泄漏造成的。尽管只是说这些调用应该不惜一切代价避免,并且是不好的,过于简单化了一些事情。在这些情况下,我也设置为空,不仅仅是处理,这是不是太过分了?吹毛求疵,但在处理之前最好将图像从picturebox中拉出。在设置新图像之前,我在referencesource中看不到访问图像的任何内容,但(在我看来)处置已与其他对象共享的对象不是一个好主意。所以我会做一些类似于
Image oldImage=webcam\u PictureBox.Image;webcam_PictureBox.Image=(位图)frame.Clone();oldImage?.Dispose()@LasseVågsætherKarlsen是的,这确实是一件合理的事情。@GuidoG-假设发布代码而不是调试,GC和JIT不需要太多帮助。如果在
Dispose
之后没有再次读取
oldImage
,则该变量在GC期间不会保持任何活动状态。似乎这就是问题所在!我根据Evk更新的答案编辑了代码,现在我的内存使用量保持在60MB,没有垃圾收集!谢谢大家。
var oldImage = webcam_PictureBox.Image;
webcam_PictureBox.Image = (Bitmap)frame.Clone();
if (oldImage != null)
    oldImage.Dispose();