.NET Core:使用SemaphoreSlim实现异步日志器的文件写入问题
日志实现问题排查
需求目标
- 日志类需输出到文件
- 必须保留消息顺序
- 调用Log方法不阻塞调用线程
- 调用Log方法必须线程安全(支持多线程调用)
测试代码
Ilogger log = new Logger(); Thread t1 = new Thread(LongRunningTask); Thread t2 = new Thread(LongRunningTask2); t1.Start(); t2.Start(); Console.WriteLine("Hello, World!"); async void LongRunningTask() { for (int i = 0; i < 10; i++) { await log.Info("Thread-1 - " + i.ToString()); } } async void LongRunningTask2() { for (int i = 0; i < 10; i++) { await log.Info("Thread-2 - " + i.ToString()); } }
Logger实现代码
internal class Logger : Ilogger { SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); public async Task Info(string message) { try { await semaphoreSlim.WaitAsync(); Console.WriteLine(message); //await File.WriteAllTextAsync("C://test.txt", message); } finally { semaphoreSlim.Release(); } } }
遇到的错误
无法访问文件'C:\test.txt',因为它正被另一个进程占用
问题原因及解决
最初使用File.WriteAllTextAsync时,该方法每次都会覆盖文件原有内容,且其文件打开逻辑会导致多线程场景下出现文件占用冲突。替换为File.AppendAllTextAsync后问题解决,因为该方法以追加模式打开文件,既保证日志内容不被覆盖,也能正确处理并发写入的文件访问逻辑。
内容的提问来源于stack exchange,提问作者Satheesh
相关产品推荐
相关产品推荐

