I have a private method in my MVVM view model that is called when the user presses a button on the view. In this method I want to ask the user to specify a file to save, and then call a static class library to perform some image processing (reading files from disc, doing some minor processing and writting them to an mp4 file using ffmediaToolkit.
private void makeMP4()
{
Microsoft.Win32.SaveFileDialog saveFileDialog = new Microsoft.Win32.SaveFileDialog();
saveFileDialog.Filter = "Media File (*.mp4)|*.mp4";
saveFileDialog.InitialDirectory = @"D:\temp\mp4output\";
saveFileDialog.FileName = myImageHandler.SuggestedFileName ".mp4";
// If I remove the following line, memory usage is stable at 1GB. If I keep this line
// memory grows linearly until program terminates.
_ = saveFileDialog.ShowDialog();
// I also tried passing current window handle to ShowDialog (with same outcome):
//_ = saveFileDialog.ShowDialog(Application.Current.Windows.OfType<MainWindow>().FirstOrDefault());
MP4Maker mp4Maker = new(myImageHandler);
mp4Maker.GenerateMP4(@"D:\temp\mp4maker\hardcodedFileName.mp4");
}
As explained by the comments in the code above, if I call the ShowDialog method my applicaiton consumes too much memory while processing the mp4 file. But if I omit the call to ShowDialog, the memory usage is stable at about 1GB.
Two suggested solutions I've seen (and reasons they have not worked for me) are:
- Passing the current window (parent/owner) handle to the ShowDialog method (see my attempt to do this commented out in code above: This didn't change the memory usage.
- Using system.windows.forms.savefiledialog as an alternative to Microsoft.Win32.SaveFileDialog: I wasn't able to do this because I am using .Net5 (my understanding is that you can't refernce System.windows.forms from a .net5 application?)
Can anybody see why calls to ShowDialog are causing memory leakage and how to prevent it? Thank you.
CodePudding user response:
After running the SaveFileDialog.ShowDialog
you should try running
GC.Collect(); GC.WaitForPendingFinalizers();
Which should force .Net to clean up any memory relating to the previous calls before then calling the next routines.