【问题标题】:How do I make a static class thread-safe?如何使静态类线程安全?
【发布时间】:2013-05-08 03:36:01
【问题描述】:

我有一个简单的静态日志记录类。但是,它绝对不是线程安全的,因为每个调用都试图写入同一个文件。我得到了这些例外:

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) 
...

使其线程安全的最佳方法是什么?

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);
    }
}

作为一个日志功能,我希望能够从我的代码的许多不同部分访问它(因此,我选择它是静态的)。但是,我想为了使它成为线程安全的,我总是必须将一个公共对象传递给 lock() on,我认为这违背了静态函数的目的。还是不是这样?

【问题讨论】:

  • 为什么不改为单例呢?

标签: c# wpf logging thread-safety static-methods


【解决方案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);
        }
    }
}

【讨论】:

  • lock ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread attempts to enter a locked code, it will wait, block, until the object is released.
  • 这个解决方案是否比创建一个接受对象的非静态类(可能有一个接受单个字符串的构造函数:要记录的消息)并锁定它更可取?
  • +1。 @raney - 锁定什么?您需要lock 围绕写入文件(每个文件最多只能锁定一个对象,示例代码可以接受所有文件的一个静态锁定)。请注意,对于真正的日志记录,最好使用现有的解决方案。
【解决方案2】:

在你的 LogMessageToFile 方法中,你需要一个锁来防止多线程访问:

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);
    }
}

【讨论】:

  • - 1 _myloc 必须是静态的才能在静态方法中访问!
猜你喜欢
  • 2012-09-22
  • 2015-03-24
  • 1970-01-01
  • 2011-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-16
  • 1970-01-01
相关资源
最近更新 更多