我什么时候应该使用 GC.SuppressFinalize()?

发布于 2024-07-07 11:41:36 字数 70 浏览 10 评论 0原文

在.NET中,什么情况下应该使用GC.SuppressFinalize()?

使用此方法给我带来什么好处?

In .NET, under which circumstances should I use GC.SuppressFinalize()?

What advantage(s) does using this method give me?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦与时光遇 2024-07-14 11:41:36

SuppressFinalize 只能由具有终结器的类调用。 它通知垃圾收集器 (GC) this 对象已被完全清理。

当您拥有终结器时,推荐的 IDisposable 模式是:

public class MyClass : IDisposable
{
    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // called via myClass.Dispose(). 
                // OK to use any private object references
            }
            // Release unmanaged resources.
            // Set large fields to null.                
            disposed = true;
        }
    }

    public void Dispose() // Implement IDisposable
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~MyClass() // the finalizer
    {
        Dispose(false);
    }
}

通常,CLR 在创建对象时会使用终结器对其进行标记(使创建它们的成本更高)。 SuppressFinalize 告诉 GC 该对象已正确清理,不需要进入终结器队列。 它看起来像一个 C++ 析构函数,但其​​行为却一点也不像。

SuppressFinalize 优化并非微不足道,因为您的对象可以在终结器队列上等待很长时间。 不要试图对您提醒的其他对象调用 SuppressFinalize。 这是一个即将发生的严重缺陷。

设计指南告诉我们,如果您的对象实现了 IDisposable,则不需要终结器,但如果您有终结器,则应该实现 IDisposable 以允许对类进行确定性清理。

大多数时候,您应该能够使用 IDisposable 来清理资源。 仅当您的对象持有非托管资源并且需要保证这些资源被清理时,您才应该需要终结器。

注意:有时,程序员会添加终结器来调试自己的 IDisposable 类的构建,以测试代码是否已正确处理其 IDisposable 对象。

public void Dispose() // Implement IDisposable
{
    Dispose(true);
#if DEBUG
    GC.SuppressFinalize(this);
#endif
}

#if DEBUG
~MyClass() // the finalizer
{
    Dispose(false);
}
#endif

SuppressFinalize should only be called by a class that has a finalizer. It's informing the Garbage Collector (GC) that this object was cleaned up fully.

The recommended IDisposable pattern when you have a finalizer is:

public class MyClass : IDisposable
{
    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // called via myClass.Dispose(). 
                // OK to use any private object references
            }
            // Release unmanaged resources.
            // Set large fields to null.                
            disposed = true;
        }
    }

    public void Dispose() // Implement IDisposable
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~MyClass() // the finalizer
    {
        Dispose(false);
    }
}

Normally, the CLR keeps tabs on objects with a finalizer when they are created (making them more expensive to create). SuppressFinalize tells the GC that the object was cleaned up properly and doesn't need to go onto the finalizer queue. It looks like a C++ destructor, but doesn't act anything like one.

The SuppressFinalize optimization is not trivial, as your objects can live a long time waiting on the finalizer queue. Don't be tempted to call SuppressFinalize on other objects mind you. That's a serious defect waiting to happen.

Design guidelines inform us that a finalizer isn't necessary if your object implements IDisposable, but if you have a finalizer you should implement IDisposable to allow deterministic cleanup of your class.

Most of the time you should be able to get away with IDisposable to clean up resources. You should only need a finalizer when your object holds onto unmanaged resources and you need to guarantee those resources are cleaned up.

Note: Sometimes coders will add a finalizer to debug builds of their own IDisposable classes in order to test that code has disposed their IDisposable object properly.

public void Dispose() // Implement IDisposable
{
    Dispose(true);
#if DEBUG
    GC.SuppressFinalize(this);
#endif
}

#if DEBUG
~MyClass() // the finalizer
{
    Dispose(false);
}
#endif
甜点 2024-07-14 11:41:36

SupressFinalize 告诉系统在终结器中应该完成的任何工作都已经完成,因此不需要调用终结器。 来自 .NET 文档:

实现 IDisposable 的对象
接口可以调用这个方法
IDisposable.Dispose 方法
防止垃圾收集器
调用 Object.Finalize
不需要它的对象。

一般来说,大多数 Dispose() 方法都应该能够调用 GC.SupressFinalize(),因为它应该清理将在终结器中清理的所有内容。

SupressFinalize 只是提供一种优化,使系统不必费心将对象排队到终结器线程。 正确编写的 Dispose()/finalizer 无论是否调用 GC.SupressFinalize() 都应该正常工作。

SupressFinalize tells the system that whatever work would have been done in the finalizer has already been done, so the finalizer doesn't need to be called. From the .NET docs:

Objects that implement the IDisposable
interface can call this method from
the IDisposable.Dispose method to
prevent the garbage collector from
calling Object.Finalize on an
object that does not require it.

In general, most any Dispose() method should be able to call GC.SupressFinalize(), because it should clean up everything that would be cleaned up in the finalizer.

SupressFinalize is just something that provides an optimization that allows the system to not bother queuing the object to the finalizer thread. A properly written Dispose()/finalizer should work properly with or without a call to GC.SupressFinalize().

淡写薰衣草的香 2024-07-14 11:41:36
Dispose(true);
GC.SuppressFinalize(this);

如果对象有终结器,.net 会将引用放入终结队列中。

由于我们调用了Dispose(true),它清除了对象,因此我们不需要终结队列来完成这项工作。

因此,调用 GC.SuppressFinalize(this) 删除终结队列中的引用。

Dispose(true);
GC.SuppressFinalize(this);

If object has finalizer, .net put a reference in finalization queue.

Since we have call Dispose(true), it clear object, so we don't need finalization queue to do this job.

So call GC.SuppressFinalize(this) remove reference in finalization queue.

世态炎凉 2024-07-14 11:41:36

如果一个类或从它派生的任何东西可能会使用终结器保存对对象的最后一个实时引用,则 GC.SuppressFinalize(this)GC.KeepAlive(this) code> 应该在任何可能受到该终结器不利影响的操作之后对对象调用,从而确保终结器在该操作完成之前不会运行。

在任何没有终结器的类和有终结器的类中,GC.KeepAlive()GC.SuppressFinalize(this) 的成本本质上是相同的一般应该调用GC.SuppressFinalize(this),因此使用后一个函数作为Dispose()的最后一步可能并不总是必要的,但也不会出错。

If a class, or anything derived from it, might hold the last live reference to an object with a finalizer, then either GC.SuppressFinalize(this) or GC.KeepAlive(this) should be called on the object after any operation that might be adversely affected by that finalizer, thus ensuring that the finalizer won't run until after that operation is complete.

The cost of GC.KeepAlive() and GC.SuppressFinalize(this) are essentially the same in any class that doesn't have a finalizer, and classes that do have finalizers should generally call GC.SuppressFinalize(this), so using the latter function as the last step of Dispose() may not always be necessary, but it won't be wrong.

挽袖吟 2024-07-14 11:41:36

该方法必须在实现 IDisposable 的对象的 Dispose 方法上调用,这样,如果有人调用该方法,GC 就不会再次调用终结器处置方法。

请参阅:GC.SuppressFinalize(Object) 方法 - Microsoft Docs

That method must be called on the Dispose method of objects that implements the IDisposable, in this way the GC wouldn't call the finalizer another time if someones calls the Dispose method.

See: GC.SuppressFinalize(Object) Method - Microsoft Docs

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文