0

I am working on an application which reads paths of all the text files from a folder into a list. It reads each file, creates a temporary output file, overwrites the original file with temporary output file and deletes the temporary output file.

Following is my code:

    foreach (string lF in multipleFiles)
    {
        int lineNumber = 0;
        using (StreamReader sr = new StreamReader(lF))
        {
            using (StreamWriter sw = new StreamWriter(lF + "Output"))
            {
                while (!sr.EndOfStream)
                {

                    //LOGIC

                    sw.WriteLine(line);
                }
            }
        }
        File.Copy(lF + "Output", lF, true);
        //File.Delete(lF + "Output");
        try
        {

            File.Delete(lF + "Output"); <--- ERROR HERE
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

I am unable to delete the temporary output file due to the following error:

{"The process cannot access the file '' because it is being used by another process."}

The error does not occur for every file but only a few. None of the files are open or being used by any other application.

How can the temporary file be deleted?

UPDATE: Refereed to Does FileStream.Dispose close the file immediately?

Added Thread.Sleep(1) before File.Delete(), The issue still exists. Tried increasing the sleep value to 5. No luck.

Tango
  • 386
  • 1
  • 6
  • 29
  • Could be related: https://stackoverflow.com/questions/6350224/does-filestream-dispose-close-the-file-immediately –  Sep 30 '17 at 08:21
  • @someone I tried adding Thread.Sleep(1). The error still occurs. I even tried increasing the sleep value to 5. – Tango Sep 30 '17 at 08:34
  • 2
    How about 50 or 500? 1 or 5 milliseconds is not a lot. –  Sep 30 '17 at 08:44
  • @someone it seems to work. So does rene's answer. Thank you for pointing me into the right direction. I have no idea bitlocker or antivirus can have an influence on it. – Tango Sep 30 '17 at 09:10

1 Answers1

0

You always run the risk that an virus scanner or some other driver in the stack still holds on to that file or its directory entry. Use some retry mechanisms but that still doesn't guarantee you'll be able to remove that file as the file operations are not atomic, so any process can open that file between your calls trying to delete it.

var path = lf + "Output";
// we iterate a couple of times (10 in this case, increase if needed)
for(var i=0; i < 10; i++) 
{
    try 
    {
        File.Delete(path);
        // this is success, so break out of the loop
        break;
    } catch (Exception exc) 
    {
         Trace.WriteLine("failed delete #{0} with error {1}", i, exc.Message);
         // allow other waiting threads do some work first
         // http://blogs.msmvps.com/peterritchie/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program/
         Thread.Sleep(0);
         // we don't throw, we just iterate again
    }
}
if (File.Exists(path)) 
{
    // deletion still not happened
    // this is beyond the code can handle
    // possible options:
    // store the filepath to be deleted on startup
    // throw an exception
    // format the disk (only joking)
}

Code slightly adapted from my answer here but that was in a different context.

rene
  • 41,474
  • 78
  • 114
  • 152