【发布时间】:2018-11-21 19:55:51
【问题描述】:
我有一个小班,我拼凑在一起来实现一个快速记录器。我用在构造函数中实例化的私有System.IO.StreamWriter 组成它。因为我使用的方式是阻止我实现using 块,所以我添加了一个终结器并在其中调用StreamWriter 的Dispose() 方法。但是,在执行时,该终结器会引发异常,因为 StreamWriter 已被释放。
System.ObjectDisposedException - 无法访问已关闭的文件。
我很困惑这是怎么发生的,我想知道这是否意味着我不需要担心清理 StreamWriter。这是我的课:
public class TextFileLogger : AbstractTextLogger
{
private const string LogPath = @"C:\";
private const string LogFileName = "MyFile.log.txt";
private readonly StreamWriter _writer;
public TextFileLogger()
{
_writer = new StreamWriter($"{LogPath}{LogFileName}", true);
_writer.AutoFlush = true;
}
~TextFileLogger()
{
_writer.Dispose();
}
protected override void WriteLine(string line)
{
_writer.WriteLine(line);
}
}
【问题讨论】:
-
你不能那样做。终结器(又名析构函数)在单独的线程上运行,不保证您的对象所引用的其他托管对象仍然存在。您应该在终结器中清理的唯一内容是非托管资源。使您的 TextFileLogger Disposable(实现 IDisposable)并阅读“Dispose Pattern”以使其正确。如果一个类没有原生资源(如你的),它不应该有终结器
-
@Flydog57 - 我熟悉 IDisposable 的实现,并且之前做过几次。我想我可以以某种方式在我的类中处理 StreamWriter 而不需要 using 块。由于这是一个快速而肮脏的临时事情,我可能只需要在每次调用 WriteLine 时更新 StreamWriter,以便我可以在 using 块中使用它。这太糟糕了,根据我的测量,执行时间会长约 14.5 倍,但对于一个短暂的项目,我宁愿承受性能损失,也不愿完全重新架构所有内容。
-
为代码中的其他地方添加一个 Dispose 方法。只要它在您的正常代码中,您就可以将其丢弃。然而,一旦你进入终结器代码,所有的“托管代码保证”大部分都会从桌面上消失。终结器很容易搞砸。
标签: c# .net idisposable finalizer