Tango Tango - 3 years ago 122
C# Question

C# - Unable to delete a file after copying and overwritting

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.

Answer Source

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download