C# .NET2.0:File.AppendAllText(…)-线程安全实现 作为一个懒惰的好奇心的练习,比其他任何事情都要考虑以下简单的日志记录类: internal static class Logging { private static object threadlock; static Logging() { threadlock = new object(); } internal static void WriteLog(string message) { try { lock (threadlock) { File.AppendAllText(@"C:\logfile.log", message); } } catch { ...handle logging errors... } } }

C# .NET2.0:File.AppendAllText(…)-线程安全实现 作为一个懒惰的好奇心的练习,比其他任何事情都要考虑以下简单的日志记录类: internal static class Logging { private static object threadlock; static Logging() { threadlock = new object(); } internal static void WriteLog(string message) { try { lock (threadlock) { File.AppendAllText(@"C:\logfile.log", message); } } catch { ...handle logging errors... } } },c#,file-io,.net-2.0,thread-safety,C#,File Io,.net 2.0,Thread Safety,在文件.AppendAllText(…)周围是否需要锁,或者该方法本身的实现是否具有线程安全性 搜索与此相关的信息会产生许多相互矛盾的信息,有人说是,有人说不是。MSDN什么也没说。文件。AppendAllText将获取日志文件上的独占写锁,这将导致任何试图访问该文件的并发线程抛出异常。因此,是的,您需要一个静态锁对象来防止多个线程同时尝试写入日志文件并引发IOException 如果这将成为一个问题,我真的建议登录到数据库表,这将更好地处理并发日志编写器 或者,您可以使用线程安全的(好吧,它将

文件.AppendAllText(…)
周围是否需要
,或者该方法本身的实现是否具有线程安全性


搜索与此相关的信息会产生许多相互矛盾的信息,有人说是,有人说不是。MSDN什么也没说。

文件。AppendAllText将获取日志文件上的独占写锁,这将导致任何试图访问该文件的并发线程抛出异常。因此,是的,您需要一个静态锁对象来防止多个线程同时尝试写入日志文件并引发
IOException

如果这将成为一个问题,我真的建议登录到数据库表,这将更好地处理并发日志编写器


或者,您可以使用线程安全的(好吧,它将为您执行锁定;我宁愿尽可能少地编写自己的多线程代码)。

它是线程安全的,因为它通过读取共享打开文件,所以假设您的文件系统遵守文件锁定,一次只允许一个线程写入文件。但是,如果其他线程试图读取同一文件,则可能会进行脏读。

测试并行写入表明,如果要注释掉lock语句,则会出现System.IO.IOException

[Test]
public void Answer_Question()
{
    var ex = Assert.Throws<AggregateException>(() => Parallel.Invoke(
        () => Logging.WriteLog("abc"),
        () => Logging.WriteLog("123")
    ));

    // System.IO.IOException: The process cannot access the file 'C:\Logs\thread-safety-test.txt' because it is being used by another process.
    Console.Write(ex);
}
[测试]
公开无效答案(问题)
{
var ex=Assert.Throws(()=>Parallel.Invoke(
()=>Logging.WriteLog(“abc”),
()=>Logging.WriteLog(“123”)
));
//System.IO.IOException:进程无法访问文件“C:\Logs\thread safety test.txt”,因为其他进程正在使用该文件。
控制台写入(ex);
}

和其他线程在尝试写入时会抛出异常。这是矛盾的。如果File.AppendAllText具有独占写入锁,为什么需要单独的锁?您误解了,正是该文件被锁定进行写入。因此,任何其他试图同时写入的线程都将收到一个异常。为了防止这种情况,您必须在程序中使用锁序列化写入。如果您使用的是大型关系数据库,请不要浪费宝贵的数据库资源进行日志记录,否则如果您使用的是lite nosql数据库,那么登录数据库也不错。如果您希望在本地进行日志记录,而不是自己写入文件系统,请使用类似windows事件日志的内容。但是,如果需要线程安全和非阻塞,为什么不为每个日志编写一个新文件,而不是追加?