如何关闭被多对象引用的C# Logger类中的StreamWriter?
解决Logger类中StreamWriter的资源释放问题
针对你遇到的StreamWriter关闭时机问题,最规范的做法是让Logger类实现IDisposable接口,通过Dispose模式管理资源,既能让用户在合适时机手动释放,也能通过using语句自动处理。
修改后的Logger类代码
internal class Logger : IDisposable { private readonly string logFilePath; private StreamWriter? writer; private bool disposed = false; public Logger(string name) { string date = DateTime.Now.ToString("yyyy-MM-dd"); logFilePath = string.Format(".\\logs\\{0}_log_{1}.log", name, date); // 简化逻辑:StreamWriter的append参数设为true,自动处理文件存在/不存在的情况 writer = new StreamWriter(logFilePath, true); } internal void Log(string message) { if (disposed) throw new ObjectDisposedException(nameof(Logger)); string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); writer.WriteLine("{0} - {1}", time, message); // 可选:立即刷新缓冲区,避免程序崩溃时丢失未写入的日志 writer.Flush(); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { // 释放托管资源:关闭并销毁StreamWriter writer?.Close(); writer?.Dispose(); } writer = null; disposed = true; } } // 析构函数:作为最后保障,即使忘记调用Dispose,GC回收时也会尝试释放资源 ~Logger() { Dispose(false); } }
使用方式
- 推荐:用using语句自动释放
当Logger对象的使用范围明确时,用using包裹,超出范围后会自动调用Dispose关闭StreamWriter:
using (var logger = new Logger("MyApp")) { logger.Log("程序启动完成"); // 执行其他日志操作 } // 此处logger已自动释放资源
- 手动调用Dispose
如果Logger是全局对象或使用范围不明确,在确定不再使用时手动调用Dispose:
var logger = new Logger("MyApp"); logger.Log("执行了某个操作"); // 不再需要日志功能时 logger.Dispose();
额外优化说明
- 简化了文件打开逻辑:StreamWriter的
append参数设为true后,不管文件是否存在都会自动追加内容,无需提前判断File.Exists。 - 添加了资源释放校验:避免在Logger已释放后调用
Log方法引发异常。 - 可选的
Flush调用:默认StreamWriter会缓冲写入内容,调用Flush能确保日志立即写入文件,降低程序意外退出时的日志丢失风险。
内容的提问来源于stack exchange,提问作者BeeFriedman
相关产品推荐
相关产品推荐

