Search code examples
c#processdisposeusingnaudio

Process confliction C#


I have the following code:

while (condition == true)
{
    //First part
    using (var stream = File.Create(audioPath))
    {
        using (WaveFileWriter writer = new WaveFileWriter(stream, waveFormat))
        {
            writer.Write(audioBytes.ToArray(), 0, audioBytes.ToArray().Length);
        }
    }
    //Second part
    using (Process.Start("cmd.exe", commands)) { };
    Thread.Sleep(1000);
}

The first part saves a byte array to an audio file, then the second part of my code runs a .cmd file that does some processing on the code. However, this above code returns the error

the process cannot access the file (audioPath) because it is being used by another process.

I have read some other answers and have encountered this problem before but always managed to solve it with a using statement.

Both parts run correcly independently (when the other part is commented out). I am running this on Windows Server 2016 if that has any affect. I have added permissions to the folder/file also and because they both work independently, I doubt it's a permissions issue.

Is it possible that the using statement is not disposing correctly?


Solution

  • Are you really generating files by the same name? audioPath doesn't seem to change.

    while (condition == true)
    {
        //First part
        using (var stream = File.Create(audioPath))
        {
            using (WaveFileWriter writer = new WaveFileWriter(stream, waveFormat))
            {
                writer.Write(audioBytes.ToArray(), 0, audioBytes.ToArray().Length);
            }
        }
        //Second part
        using (Process.Start("cmd.exe", commands)) { };
        Thread.Sleep(1000);
    }
    

    Consider the following:

    1. The auditPath is written.
    2. The cmd-command starts using it - you don't wait for it to finish.
    3. Since you don't wait for it to finish, the loop enters the next iteration and a new auditPath is written while the cmd-command already is using the "previous" one.

    alternatively

    1. Before the cmd-command actually has started (but after the Process.Start() has already completed), the loop comes to the next iteration and opens a new "version" of auditPath, writing to it.
    2. The cmd-command finally starts to access the file and you get the seen error.

    All in all you have a race condition here. Make sure you wait for Process to finish, e.g.

    using (var proc = Process.Start(...)) 
    {
       proc.WaitForExit();
       // You might want to check `proc.ExitCode`, etc.
    }
    

    before running the next loop-cycle.

    Key take-away: Process.Start() is not synchronous. If you need to wait for the launched command to finish, you need to explicitly do it, otherwise it continues to run in the background and might interfere with your other logic - as it currently does.