我可以在终结器方法中使用哪些对象?

时间:2011-08-06 01:52:34

标签: c# .net

我有一个类应该在处理或完成时删除一些文件。在终结器中我不能使用其他对象,因为它们可能已经被垃圾收集了。

我是否遗漏了关于终结者的一些观点并且可以使用字符串?

UPD:类似的东西:

public class TempFileStream : FileStream
{
    private string _filename;

    public TempFileStream(string filename)
        :base(filename, FileMode.Open, FileAccess.Read, FileShare.Read)
    {
        _filename = filename;
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (_filename == null) return;

        try
        {
            File.Delete(_filename); // <-- oops! _filename could be gc-ed already
            _filename = null;
        }
        catch (Exception e)
        {
            ...
        }
    }
}

3 个答案:

答案 0 :(得分:22)

答案 1 :(得分:1)

尚未提及的另一点是,尽管人们可能不期望在使用对象时对象的终结器会运行,但是终结机制并不能确保这一点。终结器可以在任意未知的线程上下文中运行;因此,他们应该避免使用任何不是线程安全的类型,或者应该使用锁定或其他方法来确保它们只以线程安全的方式使用东西。注意终结器应该使用Monitor.TryEnter而不是Monitor.Enter,并且如果意外地保持锁定,则尽可能优雅地行动。请注意,由于终结器不应该在对象仍在使用时运行,因此意外保持锁定的事实通常会表明终结器已经提前运行。根据使用锁的代码的设计,可以让终结器设置一个标志并再次尝试获取锁,并且在释放它之后使用任何其他使用锁检查的代码是否设置了该标志。如果是,请重新注册该对象以进行最终确定。

在所有线程场景中正确处理终结清理很困难。最终化可能看起来并不复杂,但是没有方便的自动化机制,通过这种机制,对象可以确保在使用相关对象时终结器不会运行。因此,终结器具有许多微妙的线程安全问题。忽略此类问题的代码“通常”会起作用,但有时可能会以难以诊断的方式失败。

答案 2 :(得分:0)

您可以在终结器中调用dispose方法,并在Dispose方法中使用文件清理代码。除此之外,您还可以将布尔值传递给您的dispose方法,该方法指示您正在从终结器中调用它。

有关正确使用Dispose和Fianlizers的绝佳参考,请阅读Proper use of the IDisposable interface

相关问题