.NET 2.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... } } } 

lock需要围绕File.AppendAllText(...)还是通过自己的实现本身就是线程安全的方法?

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

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

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

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

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

 [Test] public void Answer_Question() { var ex = Assert.Throws(() => 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); } 

它是线程安全的,因为它使用Read共享打开文件,所以假设你的文件系统尊重文件锁,一次只允许一个线程写入文件。 但是,如果其他线程尝试读取同一文件,则可能会出现脏读。