문제

니다.NET IDisposable 패턴 는 당신이 쓰는 경우에 종료자,그리고 구현하 IDisposable,는 종료자 요구를 명시적으로 호출을 처분 할 수 있습니다.이것은 논리적이며,무엇이 나는 항상 수행에 매우 드문 경우가 종료자용해야 할 수도 있습니다.

그러나 무엇이 일어나면 그냥 이렇:

class Foo : IDisposable
{
     public void Dispose(){ CloseSomeHandle(); }
}

고 구현하지 않 종료자 또는 아무것도.것 프레임워크를 호출 폐기 위한 방법을까?

그래 내가 이것을 깨닫게 소리 벙어리,그리고 모든 논리에 의미 없다는 것을,하지만 나는 항상 2 가지의 뒷면에서 내리는 만들어 나에게 잘 모르겠.

  1. 누군가가 몇 년 전에 한 번 말하는 것이 사실 이 작업을 수행하고,그 사람은 아주 솔리드 트랙 기록의"알고 있는 그들의 물건입니다."

  2. 컴파일러/framework 는 기타의 것에 따라 인터페이스를 구현할(예를 들어:foreach,확장 방법,직렬화 특성을 기반으로,etc.),그래서 그것은 말이 될 수 있습니다'매직'너무입니다.

는 동안 내가 읽은 물건을 많이 그것에 대해 많은 것을 암시된 적이 없습니다 예 또는 아니오 대답하여 이 질문입니다.

도움이 되었습니까?

해결책

니다.Net 쓰레기 수집가를 호출한다.을 마무리 방법에 객체를 쓰레기 모음.By 기본아무것도 해야 합 overidden 하려는 경우 무료로 추가적인 자원입니다.

폐기지 않은 자동으로 호출해야 합 에 명 라면 리소스를 같이에서'사용'또는'하려고 마지막으로'블록

http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx 자세한 내용

다른 팁

을 강조하고 싶 Brian 지점에서 그의 의견이기 때문에,그것은 중요합니다.

종료자하지 않은 결정적 소멸자에서 같은 C++.다른 사람들이 지적으로 보장은 없을 때의 것이라는,실제로는 경우에 충분한 메모리가 있는 경우 호출됩니다.

하지만 나쁜 일에 대한 종료자는 브라이언했다,그것은 당신의 개체를 살아남을 쓰레기 컬렉션입니다.이 나쁜 될 수 있습니다.왜?

로하지 않을 수도 있습니다 알다시피,GC 으로 분할대-Gen0,1,2,플러스 크 객체를 힙.분할은-당신은 하나의 블록의 메모리 있지만,포인터가 어디 Gen0 개체를 시작하고 끝입니다.

생각이 프로세스가는 당신은 가능성이 많이 사용하는 개체의 것이 짧은 살았습니다.그래서 그들은 쉽게해야하고 빠른 GC 을 얻-Gen0 개체입니다.있을 때 그래서 메모리 첫 번째는 것입니다 Gen0 컬렉션입니다.

지금,해결 되지 않으면 충분한 압력,그리고 Gen1 스위치(재실행 Gen0)다음으면 여전히 충분하지 않습니다,그것은 Gen2 스위치(재실행 Gen1Gen0)입니다.그래서 청소하는 오래된 개체가 시간이 걸릴 수 있고 오히려 비싼(이후의 스레드를 일시 중단할 수 있습하는 동안 동작).

이것이 의미하는 경우 다음과 같은 것이 가능합니다.

~MyClass() { }

귀하의 개체,무슨 상관 없이 살고있는 것,2 세대.이 때문에 GC 없는 방법이 종료자는 동안 가비지 컬렉션입니다.그래서 객체해야 하는 확정되는 이동하는 특별한 큐를 청소하여 다른 스레드(스레드가 종료자는 경우에 당신을 죽이는 모든 종류의 나쁜 일이 일어나기).이 귀하의 개체 걸 더 이상의 주위에,그리고 잠재적으로 힘을 더 가비지 컬렉션이 있습니다.

그래서,이 모든 것은 포인트 홈 드라이브를 사용할 IDisposable 를 깨끗한 리소스를 가능하고 심각하게는 방법을 찾기 위해 노력하 주변의 사용 종료자.그것은에의 응용 프로그램의 최대 관심사.

거기에 많은 좋은 토론이 이미 여기에,그리고 저는 조금 늦게 당사자,그리고 몇 가지 포인트를 추가하 myself.

  • 쓰레기 collecter 지 않을 직접 실행하는 폐기하는 방법에 대한 당신.
  • GC 실행을 종료자가 느끼는 경우 다음과 같습니다.
  • 한 가지 일반적인 패턴을 사용하는 개체에 대한 종료자는 그것을 가지고하는 메소드를 호출해서 이 협약으로 정의 폐기(bool 처분)통과 거짓을 나타내는 전화로 만들었는 종료 때문에 오히려 보다 명시적 처분하다.
  • 이 때문에 안전하지 않다면 어떤 가정에 다른 객체를 관리하는 동안 마무리 오브젝트(그들은 이미 완료되).

class SomeObject : IDisposable {
 IntPtr _SomeNativeHandle;
 FileStream _SomeFileStream;

 // Something useful here

 ~ SomeObject() {
  Dispose(false);
 }

 public void Dispose() {
  Dispose(true);
 }

 protected virtual void Dispose(bool disposing) {
  if(disposing) {
   GC.SuppressFinalize(this);
   //Because the object was explicitly disposed, there will be no need to 
   //run the finalizer.  Suppressing it reduces pressure on the GC

   //The managed reference to an IDisposable is disposed only if the 
   _SomeFileStream.Dispose();
  }

  //Regardless, clean up the native handle ourselves.  Because it is simple a member
  // of the current instance, the GC can't have done anything to it, 
  // and this is the onlyplace to safely clean up

  if(IntPtr.Zero != _SomeNativeHandle) {
   NativeMethods.CloseHandle(_SomeNativeHandle);
   _SomeNativeHandle = IntPtr.Zero;
  }
 }
}

는 간단한 버전이 있지만,뉘앙스를 많이 할 수있는 당신을 여행에 패턴이 있습니다.

  • 에 대한 계약 IDisposable.처분을 나타내는 안전해야하는 전화를 여러 번(호출 폐기 개체에 이미 배치되어야 할 아무것도)
  • 그것을 얻을 수 있는 매우 복잡한 제대로 관리하는 상속의 계층 구조를 처분할 수 있는 개체는 경우에 특히 다른 레이어를 소개하는 새로운 처분할 수 있고 관리되지 않는 자원입니다.패턴에 위 폐기(bool)은 가는 것을 허용하도록 재정의되도록 관리할 수 있습니다,그러나 나는 그것을 찾을 수 있 오류가 발생하기 쉽습니다.

내 생각에,그것은 훨씬 더 나은 완전히 방지하는 데 어떤 형식을 직접 모두 포함하는 처분할 수 있는 참조하고 네이티브 리소스가 필요할 수 있는 종료.SafeHandles 제공하는 매우 깨끗한 방법에 의해 이렇게 캡슐화하는 네이티브 리소스로 처분할 수 있는 내부적으로 제공하는 자신의 종료(의 번호와 함께 같은 다른 혜택을 제거하는 동안 창 P/호출하는 기본 처리 될 수 있는 손실로 인해 비동기 예외).

단순히 정의하 SafeHandle 이소:


private class SomeSafeHandle
 : SafeHandleZeroOrMinusOneIsInvalid {
 public SomeSafeHandle()
  : base(true)
  { }

 protected override bool ReleaseHandle()
 { return NativeMethods.CloseHandle(handle); }
}

할 수 있습을 단순화하고 포함하는 유형:


class SomeObject : IDisposable {
 SomeSafeHandle _SomeSafeHandle;
 FileStream _SomeFileStream;
 // Something useful here
 public virtual void Dispose() {
  _SomeSafeHandle.Dispose();
  _SomeFileStream.Dispose();
 }
}

나는 그렇게 생각하지 않습니다.당신이 통제가 있는 경우 폐기 호출할 수 있는 이론에서 쓰는 처분하는 코드로 가정하고(예를 들어)의 존재를 다른 개체입니다.당신이 통제 할 수 없을 때 종료자라고,그래서 그것은 것 불확실을 종료자가 자동으로 호출을 처분에 귀하를 대신합니다.


편집:나는 멀리하고 테스트를 확인:

class Program
{
    static void Main(string[] args)
    {
        Fred f = new Fred();
        f = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Console.WriteLine("Fred's gone, and he's not coming back...");
        Console.ReadLine();
    }
}

class Fred : IDisposable
{
    ~Fred()
    {
        Console.WriteLine("Being finalized");
    }

    void IDisposable.Dispose()
    {
        Console.WriteLine("Being Disposed");
    }
}

지 않는 경우에 당신을 설명, 하지만 GC 전화 종료자 는 경우,당신을 위해 하나씩 있습니다.

그러나입니다.다음 쓰레기 수거하는 대신,수집된 개체는 것으로 종료 que,모든 것을 얻을 수집,그것의 종료자라고합니다.다음 컬렉션 그 후에는 해방될 것입니다.

에 따라 메모리의 앱되지 않을 수도 있습 gc 해당 개체에 대해 생성됩니다.래의 경우에는 말,파일 또는 스트림 또는 db 연결,당신을 기다려야 할 수도 있습니다 동안을 위해 관리되지 않는 리소스를 해제에 종료자는 잠시 동안 전화를 일으키는 몇 가지 문제입니다.

No,it's not called.

하지만 이것은 쉽게 잊지 않을 폐기합니다.그냥 사용 using 키워드입니다.

나는 다음과 같은 테스트를 위한 이:

class Program
{
    static void Main(string[] args)
    {
        Foo foo = new Foo();
        foo = null;
        Console.WriteLine("foo is null");
        GC.Collect();
        Console.WriteLine("GC Called");
        Console.ReadLine();
    }
}

class Foo : IDisposable
{
    public void Dispose()
    {

        Console.WriteLine("Disposed!");
    }

GC 이 전화 처분 할 수 있습니다.그 전화 종료자,그러나 이것도 보장되지는 않고 모든 상황에서.

문서 에 대한 논의를 처리하는 가장 좋은 방법이다.

에 문서 IDisposable 제공하는 아주 분명하고 상세한 설명의 행동뿐만 아니라,예제 코드입니다.GC 이지 Dispose() 방법 인터페이스에서,하지만 그것은 전화 종료자의 개체입니다.

IDisposable 패턴 주로 만들었을 것이라고 개발자에 의해 있는 경우 객체를 구현하는 IDispose 개발해야 하나를 구현하는 using 키워드 주변의 컨텍스트 객체 또는 처분하는 방법이 직접 있습니다.

실패에 대한 안전 패턴을 구현하는 종료자를 호출하 폐기()메소드가 있습니다.하지 않으면 만들 수 있는 몇 가지 메모리 누출 즉:을 만든 경우 일부 COM wrapper 를 호출하지 않는 시스템입니다.런타임입니다.Interop.마샬.ReleaseComObject(comObject)(될 것이라고에 위치한 폐기하는 방법).

마법은 없 clr 에서 전화를 폐기하는 방법을 자동으로 추적 이외의 다른 객체를 포함하는 종료자 및 저장을 그들에 종료자 테 GC 에 의해하고 그들을 부르면 몇 가지 정 추론 킥 GC 에 의해.

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