我不确定我是否可以在已经说过的关于使日志记录类线程安全的内容中添加任何内容。如前所述,要做到这一点,您必须同步对资源的访问,即日志文件,以便一次只有一个线程尝试登录它。 C# lock 关键字是执行此操作的正确方法。
但是,我将讨论 (1) 单例方法和 (2) 您最终决定使用的方法的可用性。
(1) 如果您的应用程序将其所有日志消息写入单个日志文件,那么单例模式绝对是要走的路线。日志文件将在启动时打开,在关闭时关闭,单例模式非常适合这种操作概念。但是,正如@dtb 指出的那样,请记住将类设为单例并不能保证线程安全。使用 lock 关键字。
(2) 至于该方法的可用性,请考虑以下建议的解决方案:
public class SharedLogger : ILogger
{
public static SharedLogger Instance = new SharedLogger();
public void Write(string s)
{
lock (_lock)
{
_writer.Write(s);
}
}
private SharedLogger()
{
_writer = new LogWriter();
}
private object _lock;
private LogWriter _writer;
}
我先说这个方法一般是可以的。它通过Instance 静态变量定义SharedLogger 的单例实例,并通过私有构造函数阻止其他人实例化该类。这是单例模式的精髓,但我强烈建议您阅读并遵循 Jon Skeet 关于singletons in C# 的建议,然后再走得太远。
但是,我想关注的是这个解决方案的可用性。通过“可用性”,我指的是使用此实现记录消息的方式。考虑一下调用的样子:
SharedLogger.Instance.Write("log message");
整个“实例”部分看起来是错误的,但鉴于实现,没有办法避免它。相反,请考虑以下替代方案:
public static class SharedLogger
{
private static LogWriter _writer = new LogWriter();
private static object _lock = new object();
public static void Write(string s)
{
lock (_lock)
{
_writer.Write(s);
}
}
}
请注意,该类现在是静态的,这意味着它的所有成员和方法都必须是静态的。它与前面的示例没有本质区别,但请考虑其用法。
SharedLogger.Write("log message");
编写代码要简单得多。
重点不是贬低前一种解决方案,而是建议您选择的任何解决方案的可用性是一个不容忽视的重要方面。一个好的、可用的 API 可以使代码更简单、更优雅、更易于维护。