I’m using System.Diagnostics.Process class to convert wav file to mp3 file in a separated process. The method that does the job like this:
public void ConvertWavToMp3 (TempFile srcFile, string title, Action<TempFile, Exception> complete)
{
var argument_fmt = "-S --resample 16 --tt {0} --add-id3v2 {1} {2}";
var dstFile = new TempFile(Path.GetTempFileName());
var proc = new System.Diagnostics.Process ();
proc.EnableRaisingEvents = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.FileName = "lame";
proc.StartInfo.Arguments = String.Format (argument_fmt,
title,
srcFile.Path,
dstFile.Path);
proc.Exited += delegate(object sender, EventArgs e) {
proc.WaitForExit();
srcFile.Delete();
complete(dstFile, null);
};
proc.Start();
}
I’m worried about GC because as proc is only a local variable, theoretically it doesn’t exist anymore when the method returns. Therefor, proc can be garbage collected and the callback function complete will never be called.
But I don’t really want to record proc somewhere and dispose it after the process exits, as that would expose the internal mechanism of how the wav to mp3 conversion is implemented.
Is my concern about GC valid? If GC of is potential problem, is there any way that I could prevent it without having to return the proc in this method?
BTW, I’m using Mono on linux.
Edit
Thanks for replies. I’m confirmed that I need to keep a copy of the process. So here’s what I did:
public class LameConverter : IAudioConverter
{
// We need to store a reference to the process in case it was GCed.
IList<Process> _ProcList = new List<Process>();
public void ConvertWavToMp3 (TempFile srcFile, string title, Action<TempFile, Exception> complete)
{
// .. skipped ..
proc.Exited += delegate(object sender, EventArgs e) {
lock (this) {
_ProcList.Remove(proc);
}
proc.Dispose();
srcFile.Delete();
complete(dstFile, null);
};
proc.Start();
lock (this) {
_ProcList.Add(proc);
}
}
}
As long as the caller holds a reference to LameConverter, I don’t need to worry about the GC anymore.
Any object without a root in the application is a candidate for garbage collection. In order to ensure that your callback fires you will need to find some place to store a reference to
procotherwise you will have undefined behavior.One option in your case would be to return an object that encapsulates
procwithout exposing it via the public interface. Unfortunately in your case you must leak a bit of the underlying implementation to the caller ofConvertWavToMp3in order to ensure that the desired behavior occurs.