How do I make a static class thread-safe?

14,422

Solution 1

public static class Logger
{
    private static readonly string LOG_FILENAME = "logfile.txt";
    private static readonly string LOG_FOLDER = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "App name");
    private static readonly string LOG_FULLPATH = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "App name", LOG_FILENAME);

    private static Object theLock=new Object();

    public static void LogMessageToFile(string msg)
    {
        msg = string.Format("{0:G}: {1}{2}", DateTime.Now, msg, Environment.NewLine);
        lock (theLock)
        {
            File.AppendAllText(LOG_FULLPATH, msg);
        }
    }
}

Solution 2

In your LogMessageToFile method, you need a lock to prevent multi-thread accessing:

private static Object _mylock = new Object();
public static void LogMessageToFile(string msg)
{
    lock(_mylock)
    {
       msg = string.Format("{0:G}: {1}{2}", DateTime.Now, msg, Environment.NewLine);
       File.AppendAllText(LOG_FULLPATH, msg);
    }
}
Share:
14,422
Doug
Author by

Doug

Updated on June 05, 2022

Comments

  • Doug
    Doug almost 2 years

    I have a simple simple logging class that is static. However, it's definitely not thread safe as every call attempts to write to the same file. I get these exceptions:

    The process cannot access the file 'logfile.txt' because it is being used by another process.
    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 
    ...
    

    What is the best way to make it thread safe?

    public static class Logger
    {
        private static readonly string LOG_FILENAME = "logfile.txt";
        private static readonly string LOG_FOLDER = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "App name");
        private static readonly string LOG_FULLPATH = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "App name", LOG_FILENAME);
    
        public static void LogMessageToFile(string msg)
        {
            msg = string.Format("{0:G}: {1}{2}", DateTime.Now, msg, Environment.NewLine);
            File.AppendAllText(LOG_FULLPATH, msg);
        }
    }
    

    As a logging function, I would like to be able to access it from many different parts of my code (hence, why I chose it to be static). However, I'm imagining that to make it thread safe, I'll always have to pass it a common object to lock() on, which I think defeats the purpose of a static function. Or is that not the case?