Я создаю небольшое приложение, которое показывает прямую трансляцию веб-камеры в форме Windows, а также сохраняет изображения с водяными знаками для дисков с заданным интервалом (конечная цель - создание видеоролика с интервальной съемкой).
Я использую библиотеку AForge для обработки изображений и видео.
У меня проблемы с утечкой памяти, хотя я стараюсь использовать операторы using в каждом месте, где происходит обработка изображения.
Ниже приведен код, в котором происходит обработка изображения (событие 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;
}
}
Теперь, когда я запускаю программу, я вижу, как увеличивается и уменьшается использование памяти, обычно она падает до 900 МБ, прежде чем перестать работать. Но иногда это увеличится до 2 ГБ. Иногда я даже получаю исключение нехватки памяти в этой строке:
Graphics graphics = Graphics.FromImage(frame)
Итак, потратив час или около того на попытки изменить код и найти утечку памяти, я наконец-то попробовал строку GC.Collect, которая закомментирована в коде (Shame). После этого мое использование памяти остается постоянным, менее 60 МБ. И я могу без проблем запустить программу в течение 24 часов.
Итак, я прочитал немного о GC.Collect и о том, как это плохо, например, что может потребоваться много вычислительной мощности, чтобы сделать это часто в программе. Но когда я сравниваю мощность процессора, используемую моей программой, она на самом деле не меняется независимо от того, комментирую я строку или оставляю ее. Но проблема памяти исчезнет, если я соберу в конце события нового кадра.
Я хотел бы найти решение моей проблемы, которое не включает функцию GC.collect, так как я знаю, что это плохая практика программирования, и вместо этого я должен найти источник проблемы.
Спасибо всем заранее!