GC.SuppressFinalize гарантируется?

исправленный код ниже

abstract class Employee {
public abstract void names();

public abstract void offices();
}

class Banani extends Employee {
@Override
public void names() {
    System.out.println("I am at Banani.");
}

@Override
public void offices() {
    // TODO Auto-generated method stub

}
}

class Shyamoli extends Employee {
@Override
public void names() {
    System.out.println("I am at Shyamoli");
}

@Override
public void offices() {
    // TODO Auto-generated method stub

}
}

public class javatest {
public static void main(String[] args) {
    Employee south = new Banani();
    Employee north = new Shyamoli();
    north.names();
    south.names();
}
}
6
задан Atif Aziz 25 January 2011 в 00:21
поделиться

5 ответов

Я всегда использую этот шаблон проектирования для реализации интерфейса IDisposable. (что предлагает Microsoft), и для меня GC.SuppressFinalize всегда имеет гарантию!

using System;
using System.ComponentModel;

//The following example demonstrates how to use the GC.SuppressFinalize method in a resource class to prevent the clean-up code for the object from being called twice.

public class DisposeExample
{
    // A class that implements IDisposable.
    // By implementing IDisposable, you are announcing that 
    // instances of this type allocate scarce resources.
    public class MyResource : IDisposable
    {
        // Pointer to an external unmanaged resource.
        private IntPtr handle;
        // Other managed resource this class uses.
        private readonly Component component = new Component();
        // Track whether Dispose has been called.
        private bool disposed;

        // The class constructor.
        public MyResource(IntPtr handle)
        {
            this.handle = handle;
        }

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue 
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the 
        // runtime from inside the finalizer and you should not reference 
        // other objects. Only unmanaged resources can be disposed.
        private void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!disposed)
            {
                // If disposing equals true, dispose all managed 
                // and unmanaged resources.
                if (disposing)
                {
                    // Dispose managed resources.
                    component.Dispose();
                }

                // Call the appropriate methods to clean up 
                // unmanaged resources here.
                // If disposing is false, 
                // only the following code is executed.
                CloseHandle(handle);
                handle = IntPtr.Zero;
            }
            disposed = true;
        }

        // Use interop to call the method necessary  
        // to clean up the unmanaged resource.
        [System.Runtime.InteropServices.DllImport("Kernel32")]
        private extern static Boolean CloseHandle(IntPtr handle);

        // Use C# destructor syntax for finalization code.
        // This destructor will run only if the Dispose method 
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide destructors in types derived from this class.
        ~MyResource()
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            Dispose(false);
        }
    }

    public static void Main()
    {
        // Insert code here to create
        // and use a MyResource object.
    }
}

Источник: MSDN: метод GC.SuppressFinalize

3
ответ дан 16 December 2019 в 21:46
поделиться

Одна странность, которую вы можете заметить , заключается в том, что финализатор все еще может работать, даже когда метод экземпляра все еще работает, если этот метод экземпляра не работает используйте любые переменные позже. Итак, в вашем примере кода метод Dispose не использует никаких переменных экземпляра после первой строки. Затем экземпляр может быть завершен, даже если Dispose все еще выполняется.

Если вы вставите вызов GC.KeepAlive (this) в конце Dispose метод, вы можете найти проблема исчезнет.

4
ответ дан 16 December 2019 в 21:46
поделиться

Я много раз использовал один и тот же шаблон, и GC.SupressFinalize всегда работал.

Имейте в виду, что вызов GC.ReRegisterForFinalize приведет к повторной регистрации объектов для завершения.

Всякий раз, когда я использую описанную выше технику, я всегда гарантирую, что при построении объекта включаю полную трассировку стека, чтобы можно было отследить метод, который выделил неразмещенный объект. [+1266] Например. в конструкторе используйте

StackFrame frame = new StackFrame(1);

и сообщите об этом в вашем отладочном сообщении во время финализатора.

Также я заметил, что ваш GC.SupressFinalize не входит в предложение finally; если во время удаления выбрасывается исключение, ваш финализатор объектов не будет подавлено.

0
ответ дан 16 December 2019 в 21:46
поделиться

Я бросаю InvalidOperationException в финализатор, что упрощает поиск типов, которые не были удалены должным образом. Когда вызывается Dispose (), где вызывается GC.SuppressFinalize, я никогда не получаю исключения.

1
ответ дан 16 December 2019 в 21:46
поделиться

Когда создается объект с определяемым пользователем финализатором, среда выполнения должна сохранять внутреннюю ссылку на него, чтобы, когда он становится недоступным в пользовательском коде, финализатор все еще может быть вызван в поток финализации среды выполнения. Учитывая, что время имеет существенное значение при вызове финализаторов, нет смысла держать объекты в очереди, если пользователь запросил их подавление. В моей тестовой реализации CLI я сохраняю флаг SuppressFinalizer в заголовках объектов, которые имеют определенные пользователем финализаторы. Если флаг истинен, когда поток финализатора достигает этого объекта в очереди, вызов финализатора пропускается. Я не удаляю объект из очереди, поэтому могу оставить вызов GC.SuppressFinalize () O (1) вместо O ( N ),

0
ответ дан 16 December 2019 в 21:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: