tags:

views:

41

answers:

1

I write my debug information to a file using a separate thread. During startup, I like to backup any previous file. Unfortunately, it seems the OS hangs onto the file handle for an indeterminate amount of time so when I try to write to the file, it fails.

I am using C#, .Net framework 3.5 on Windows XP. (Vista and Win7 have the same problem).

Here is the code that distills the problem, where t will throw a System.IO.IOException: "The process cannot access the file 'C:\deleteMe.txt' because it is being used by another process."

public class WriteToFile {

    static void Main(){
        String filename=@"C:\deleteMe.txt";
        String filenameBackup = @"C:\deleteMe (backup).txt";
        String value = "this is a test value";

        //MAKE FILE
        fillFile(filename, value);


        //MAKE A THREAD TO WRITE TO FILE, WHEN READY
        Semaphore readyToWrite=new Semaphore(1, 1);
        var t=new Thread(
            new ThreadStart(delegate(){
                readyToWrite.WaitOne();
                WriteToFile.fillFile(filename, value);
            })
        );
        t.Priority=ThreadPriority.Highest;
        t.Start();


        //BACKUP FILE 
        if (File.Exists(filename)) {
            File.Delete(filenameBackup);
            File.Copy(filename, filenameBackup);
            File.Delete(filename);
        }//endif

        //SIGNAL THREAD TO WRITE TO FILE
        readyToWrite.Release();
    }//method


    public static void fillFile(String filename, String value) {
        try {
            StreamWriter w = File.AppendText(filename);
            using (w) {
                w.Write(value);
                w.Flush();
            }//using
        } catch (Exception e) {
            throw new Exception("Can not write to file", e);
        }//try
    }//method


}//class

Thanks!

+2  A: 

You are initializing the Semaphore wrong. Try : new Semaphore(0, 1);

See this MSDN page.

And a WaitEvent is probably easier and more appropriate for this task.

The 2 code changes would be:

//Semaphore readyToWrite=new Semaphore(1, 1);
var readyToWrite = new ManualResetEvent(false);

//readyToWrite.Release();
readyToWrite.Set();

Also, setting the Priority is usually a bad idea. You're not going to gain anything here (it's an I/O thread), so best leave it.

Henk Holterman
+1, Yup. Starting a thread, then waiting for it is a waste of resources too. Setting the priority higher doesn't buy a faster hard disk.
Hans Passant
@Hans: agree with the Priority, I'll add that. For the rest I think this is an excerpt so I'm not sure if it is a bad design.
Henk Holterman
Thanks, I guess that was simple. My distilled code had a bug, figures.
Kyle Lahnakoski