문제

.NET에서 어떤 상황에서 사용해야합니다 GC.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은 생성 될 때 최종화기가있는 객체의 탭을 유지합니다 (생성 비용이 더 많이 듭니다). 억압제는 GC에 물체가 올바르게 정리되었으며 Finalizer 대기열로 갈 필요가 없다고 말합니다. C ++ 소멸자처럼 보이지만 하나처럼 행동하지 않습니다.

객체가 결승전 대기열에서 오랫동안 기다릴 수 있기 때문에 억제 최적화는 사소하지 않습니다. 다른 물체에 대한 억압제를 부르고 싶은 유혹을받지 마십시오. 그것은 심각한 결함이 일어나기를 기다리고 있습니다.

디자인 가이드 라인은 객체가 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

다른 팁

당신은 시스템에 Finalizer에서 수행 된 작업이 이미 완료되었다고 말하면 Finalizer를 호출 할 필요가 없습니다. .NET 문서에서 :

idisposable 인터페이스를 구현하는 객체는 idisposable 에서이 메소드를 호출 할 수 있습니다.

일반적으로 대부분의 모든 Dispose () 메소드는 GC.Supressfinalize ()를 호출 할 수 있어야합니다. 결승 분야에서 정리할 모든 것을 정리해야하기 때문입니다.

Supressfinalize는 시스템이 결승 분기 스레드에 대한 객체를 방해하지 않도록하는 최적화를 제공하는 것입니다. 적절하게 작성된 dispose ()/finalizer는 gc.supressfinalize ()에 대한 호출이 있거나없는 상태에서 제대로 작동해야합니다.

이 방법은 idisposable을 구현하는 객체의 처분 방법에서 호출되어야합니다. 이런 식으로 GC는 Dispose 메소드를 호출하는 경우 GC는 다른 시간에 다른 시간을 호출하지 않습니다.

보다: http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx

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

Object가 Finalizer가있는 경우 .NET은 Finalization 대기열에 참조를 넣습니다.

우리는 전화 dispose (ture)를 가지고 있으므로 객체가 명확 하므로이 작업을 수행하기 위해 최종 대기열이 필요하지 않습니다.

따라서 GC.Suppressfinalize (this) Finalization 대기열에서 참조를 제거하십시오.

클래스 또는 그에서 파생 된 것이라면 Finalizer가있는 객체에 대한 마지막 실시간 참조를 보유 할 수 있습니다. GC.SuppressFinalize(this) 또는 GC.KeepAlive(this) 해당 파이널 라이저의 부정적인 영향을받을 수있는 작업 후에 객체를 호출해야하므로 해당 작업이 완료 될 때까지 최종화기가 실행되지 않도록해야합니다.

의 비용 GC.KeepAlive() 그리고 GC.SuppressFinalize(this) 최종화기가없는 클래스에서는 본질적으로 동일하며 최종화기가있는 클래스는 일반적으로 전화해야합니다. GC.SuppressFinalize(this), 후자의 기능을 마지막 단계로 사용합니다. Dispose() 항상 필요하지는 않지만 잘못된 것은 아닙니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top