在.NET环境中使用opencvsharp时,有没有办法确保gc?

os8fio9y  于 2023-03-13  发布在  .NET
关注(0)|答案(1)|浏览(235)

我正在使用opencvsharp在windows窗体应用程序中进行一些图像处理,在确保GC能够在适当的时间进行收集时遇到了问题。这会在我用完进程内存时导致异常。我通过遵循各种建议修复了这个问题(把所有打开的cv iDisposables放在using块中,避免不必要的分配等)但当我转移到批处理时,我仍然在大量图像后耗尽内存。
遵循opencv论坛上的一些建议,我将代码放入一个try..catch.. finally序列中,期望GC.Collect()解决这个问题。

private void procDB_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK && Directory.Exists(_srcFolder))
            {

                _dstFolder = folderBrowserDialog1.SelectedPath;
                string[] files = Directory.GetFiles(_srcFolder);
                for (int i = 0; i < files.Length; i++) 
                {
                    try
                    {
                        if (Path.GetExtension(files[i]).ToLower() == ".jpg" ||
                            Path.GetExtension(files[i]).ToLower() == ".png" ||
                            Path.GetExtension(files[i]).ToLower() == ".gif" ||
                            Path.GetExtension(files[i]).ToLower() == ".bmp")
                        {
                            //process and save new files with 'converted ' tag in file name
                            using (Mat currentImage = ConformInputImage(Cv2.ImRead(files[i], ImreadModes.Color)))
                            {
                                using (_convMatBGR = ConvertImage(_srcMatBGR, currentImage))
                                {
                                    string outFileName = Path.Combine(_dstFolder, Path.GetFileNameWithoutExtension(files[i])) + "_conv" + Path.GetExtension(files[i]).ToLower();
                                    _convMatBGR.ImWrite(outFileName);
                                }
                            }
                        }
                    }
                    catch(Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        i--;
                    }
                    finally { GC.Collect(); }
                }
            }
        }

然而,它仍然会遇到异常,但现在我可以告诉它继续,它会很高兴地对任何数量的图像这样做。这产生了如下所示的内存使用:

斜坡上的每一步都是一个正在处理的新图像,直到遇到异常为止,此时它会清除所有垃圾,当我关闭消息框时,它会继续处理。垃圾似乎确实被收集了,但在遇到异常之前没有释放任何内存-如何修复它,使它永远不会遇到异常?n

xsuvu9jc

xsuvu9jc1#

在绝大多数情况下,你不需要手动调用GC.Collect。它会在内存不足之前自动运行。如果你遇到内存不足异常,很可能是内存泄漏。如果内存使用在异常后下降,很可能是异常导致了一些引用被释放,* 这 * 允许GC收集内存。
我想先说:
1.检查是否需要释放Cv2.ImRead的结果。即,是否记录了ConformInputImage,以便在释放结果对象时释放其输入?
1.拍摄一个内存快照并检查对象表。我希望在任何时候只有一个或两个Mat对象是活动的。如果超过这个数量,您就发现了泄漏。
1.获取两个内存快照并比较它们,是否有任何类型的对象在两个快照之间的计数增加?这可能是泄漏的候选对象。
请注意,在处理本机库时,您可能需要对释放对象提高警惕。任何托管 Package 都应实现终结器,以确保最终释放本机对象,即使您忘记调用dispose也是如此。但这并不总是能做到的,即使做到了,终结器也可能不会立即运行,甚至根本不能保证运行。

相关问题