3

When I write info to file and multiple copies of program are runnnig I get this error:

The process cannot access the file 'C:\logs\log.txt' because it is being used by another process.

code is:

// create a writer and open the file
TextWriter tw2 = File.AppendText(@"C:\logs\log.txt");

// write a line of text to the file
tw2.WriteLine(Environment.NewLine);
tw2.WriteLine(DateTime.Now + " " + "IN INFOSERVCALLER");
tw2.Flush();

How to do it in right way?

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
VextoR
  • 5,087
  • 22
  • 74
  • 109
  • 1
    Try checking if the file is in use first, see this answer http://stackoverflow.com/a/937558/799586 – Bali C Apr 18 '12 at 13:28
  • 2
    @BaliC: The only problem with first checking if a file is locked, is that it can still become locked between the time you checked and the time you open it to write to it. It is better to just try to write to the file and catch the exception if it occurs. Then try again later. – Jason Down Apr 18 '12 at 13:35

4 Answers4

1

Always encapsulate this kind of code in a using statement

using(TextWriter tw2 = File.AppendText(@"C:\logs\log.txt"))
{
    tw2.WriteLine(Environment.NewLine); 
    tw2.WriteLine(DateTime.Now + " " + "IN INFOSERVCALLER"); 
    //tw2.Flush();  // No need to flush because close alway flush.
}

The using statement calls tw2.Close() at the end of the block.
Also if you get exceptions while inside the block.

Now if the other instances of your application fails for some reason, the file is no more locked

Steve
  • 213,761
  • 22
  • 232
  • 286
  • 1
    Flush is not necessary here, as the implicit Close will also flush the stream. – Polyfun Apr 18 '12 at 13:37
  • Neither 'Close' nor 'using' will prevent exception to happen, it will just decrease the probability of exception. There is still chance that multiple instances of program will attempt to open log file in the same time. Access to file must be synchronized with appropriate synchronization primitive such as Mutex. – Ňuf Apr 18 '12 at 14:23
  • @Ňuf the exceptions will happen, but the using block ensure the correct closing of the file and then other process could use the file without bein locked out (as for flush, you and ShellShock are right, copy paste :) ) – Steve Apr 18 '12 at 14:36
  • Steve: Question was "How to do it in RIGHT WAY?". When program still throws exception instead of writing to file is IMHO not the right way. Even without "using" statement, file will be closed correctly too, with only difference that 'using' will close file immediately, without 'using' file will be closed (much) later in desctuctor. – Ňuf Apr 18 '12 at 14:53
1

Use Mutex class to synchronize access to log file from multiple processes. Call WaitOne before you open the file and call ReleaseMutex after you close the file (Flush is not enough, you must Close file or wrap it in using keyword, as other answers mentioned) when writing is done. Mutex name should start with prefix "Global\".

Ňuf
  • 6,027
  • 2
  • 23
  • 26
0

Apart from Flushing, you have to Close() the file.

Besides, if another instance is writing the file at the same time, you can't access it (until the other program calls Close().

TextWriter.Close Method

Closes the current instance of writer and releases any system resources associated with the writer

In this case the "system resource" refers to the file that keeps locked until you close it.

Malhar Chudasama
  • 343
  • 1
  • 10
JotaBe
  • 38,030
  • 8
  • 98
  • 117
0

You need to close each time you open file with text writer.

So after each operation use

// create a writer and open the file
TextWriter tw2 = File.AppendText(@"C:\logs\log.txt");

// write a line of text to the file
tw2.WriteLine(Environment.NewLine);
tw2.WriteLine(DateTime.Now + " " + "IN INFOSERVCALLER");
tw2.Flush();
tw2.Close(); 

After that again try to write on that will not create any problem further.

Malhar Chudasama
  • 343
  • 1
  • 10