Streamwriter lock does not work

I take on the C # project, and when testing it, I get errors. The error is that the log file could not be written because it is being used by another process. Here is the code:

public void WriteToLog(string msg) { if (!_LogExists) { this.VerifyOrCreateLogFile(); // Creates log file if it does not already exist. } // do the actual writing on its own thread so execution control can immediately return to the calling routine. Thread t = new Thread(new ParameterizedThreadStart(WriteToLog)); t.Start((object)msg); } private void WriteToLog(object msg) { lock (_LogLock) { string message = msg as string; using (StreamWriter sw = File.AppendText(LogFile)) { sw.Write(message); sw.Close(); } } } 

_LogLock is defined as a class variable:

  private object _LogLock = 0; 

Based on my research and the fact that this has been working in the production system for several years, I don’t know what the problem is. The lock should prevent another thread from trying to write to the log file.

The changes I made that need to be tested are a lot more than using logs. We basically add debug mode to save much more information in the log than we used to save.

Thanks for any help!

EDIT:

Thanks for the quick answers! VerifyOrCreateLogFile () uses _LogLock in the code, so this should not be a problem. He makes some entries in the log before it fails, so he does not have time to create a file.

It seems that the problem is that previously only one class created an instance of the log class, and now I have added instances to other classes. It makes sense that this will create problems. Changing the _LogLock field for static fixes the problem.

Thanks again!

+4
source share
4 answers

The lock should prevent another thread from trying to write to the log file.

This is only true if you are using a single instance of this class.

If each (or even some) of the log requests uses a separate instance, blocking will not protect you.

You can easily fix this by making the _LogLock static field:

 private static object _LogLock = 0; 

Thus, all instances will have the same lock.

+7
source

I see 2 problems with the code:

  • The lock should be the same among all the "users" of the log class, the easiest way to do is either _LogLock or the full static class
  • VerifyOrCreateLogFile may occur if two or more parallel threads call WriteToLog when _LogExists is false ...
+2
source

One possibility is that the OS does not release the file lock fast enough before you exit lock in WriteToLog , and another thread that has been blocked waiting for the lock tried to open it before the OS finishes issuing the lock file. Yes, it can happen. You also need to sleep a bit before trying to open the file, centralize the logging to the selected object (so that he and only he has access to this file, and you do not need to worry about cases of file blocking).

Another possibility is that you need to block

 if (!_LogExists) { this.VerifyOrCreateLogFile(); // Creates log file if it does not already exist. } 

The third possibility is that you have multiple instances of any class in which these methods are stored. The lock object will not be shared between instances (make it static to solve this problem).

At the end of the day, if you are not an expert at writing secure multi-threaded code, just let someone else worry about it. Use a framework that handles these problems for you (log4net?).

+1
source

you can make executable code simple

delete sw.Close () ; from your code ...

do it .... it will work fine .....

0
source

All Articles