Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从终结器中调用GC.SuppressFinalize()_C#_.net_Garbage Collection - Fatal编程技术网

C# 从终结器中调用GC.SuppressFinalize()

C# 从终结器中调用GC.SuppressFinalize(),c#,.net,garbage-collection,C#,.net,Garbage Collection,我正在学习一个类,在这个类中,我必须处理托管和非托管资源,看起来像这样(显然,只有处理部分): 然后我想到了一个主意。为什么还要麻烦第二个Dispose函数呢?为什么我不能这样做: class MyDisposingExample2 : IDisposable { public void Dispose() { // free unmanaged resources here // free managed resources here

我正在学习一个类,在这个类中,我必须处理托管和非托管资源,看起来像这样(显然,只有处理部分):

然后我想到了一个主意。为什么还要麻烦第二个Dispose函数呢?为什么我不能这样做:

class MyDisposingExample2 : IDisposable
{
    public void Dispose()
    {
        // free unmanaged resources here
        // free managed resources here
        GC.SuppressFinalize(this);
    }

    ~MyDisposingExample2()
    {
        Dispose();
    }
}
通常的处理模式解决了几个问题,所有这些问题似乎都在本例中得到了解决,而无需额外的方法

1) 如果显式调用Dispose()方法,它将释放托管资源和非托管资源,并抑制终结器,以便以后不再释放资源

2) 如果没有显式调用Dispose()方法,那么终结器将运行Dispose()、释放托管资源、释放非托管资源并抑制终结器(稍后我们将回到这一点)

从表面上看,此模式提供了前一个模式所做的一切。如果我不再需要我的对象,我可以显式地处理它;如果我忘记自己处理它,我的对象是隐式地处理的,并且不担心资源被释放两次

唯一的美中不足似乎是我正在从终结器本身内部调用GC.SuppressFinalize(),但是。。。为什么不呢

此方法在obj的对象头中设置一个位,运行时在调用终结器时检查该位

所以我所做的就是设置一点。一旦终结器运行,这不会影响它,因为位检查必须在调用终结器之前进行


由于我在任何地方都没有看到这种模式,我必须假设它有问题。我缺少什么?

您不应该从终结器中释放托管资源,这就是问题所在。您不应该从终结器中释放托管资源。然而,MSDN教授的标准模式也不是很好。去读一读斯蒂芬·克利里写的那篇文章吧,它真是让人大开眼界。总结本文,在现代应用程序中,您不应该需要编写终结器,而应该使用自定义的
SafeHandle
来管理它。您没有根据MSDN示例代码实现一次性模式。如果你问了,你可能不会问这个问题。您的替代者有一个明显的错误,但您隐藏了错误代码。请务必使用MSDN示例。您的假设是,不必要的SuppressFinalize调用是您计划中的错误。这不是问题所在;问题是终结器线程上托管资源的处置。回想一下,终结器在自己的线程上运行,托管资源可以被线程亲缘化,现在开始想象可能导致的恐怖。此外:终结器以任意顺序运行。在终结器线程上部署的托管对象可能已被终结;现在您可能在一个对象上运行两次终结逻辑;编写一个正确的终结器是非常困难的,我建议您不要尝试,理想情况下,但一定要等到您更好地理解模式后再尝试。如果你还没有足够的恐惧,我关于这个主题的系列文章可能会让你更加恐惧:
class MyDisposingExample2 : IDisposable
{
    public void Dispose()
    {
        // free unmanaged resources here
        // free managed resources here
        GC.SuppressFinalize(this);
    }

    ~MyDisposingExample2()
    {
        Dispose();
    }
}