[datatable] Dispose () DataSet 및 DataTable을해야합니까?

DataSet과 DataTable은 모두 IDisposable을 구현하므로 일반적인 모범 사례에서는 Dispose () 메서드를 호출해야합니다.

그러나 지금까지 읽은 내용에서 DataSet 및 DataTable에는 실제로 관리되지 않는 리소스가 없으므로 Dispose ()는 실제로 많은 작업을 수행하지 않습니다.

또한 using(DataSet myDataSet...)DataSet에는 DataTable 컬렉션이 있으므로 사용할 수 없습니다 .

따라서 안전하려면 myDataSet.Tables를 반복하고 각 DataTable을 삭제 한 다음 DataSet을 삭제해야합니다.

따라서 모든 DataSet 및 DataTable에서 Dispose ()를 호출하는 것이 번거 롭습니까?

추가:

당신의 그 누구 데이터 집합을 배치해야한다고 생각 : 일반적으로, 폐기에 대한 패턴을 사용하는 것 using또는try..finally 당신이 폐기 ()가 호출 될 것을 보장을 원하기 때문에.

그러나 이것은 컬렉션에 대해 추악하게 빠릅니다. 예를 들어 Dispose () 호출 중 하나에서 예외가 발생하면 어떻게해야합니까? 다음 요소를 계속 처리 할 수 ​​있도록 삼키는가 ( “나쁜”것)?

아니면 그냥 myDataSet.Dispose ()를 호출하고 myDataSet.Tables에 DataTable을 배치하는 것을 잊어 버릴 것을 제안합니까?



답변

다음은 DataSet에 Dispose가 필요하지 않은 이유를 설명하는 몇 가지 설명입니다.

처분하거나 처분하지 않겠습니까? :

DataSet의 Dispose 메서드는 상속의 부작용 때문에 만 존재합니다. 즉, 실제로는 마무리 작업에 유용한 작업을 수행하지 않습니다.

DataTable 및 DataSet 개체에서 Dispose를 호출해야합니까? MVP의 설명이 포함되어 있습니다.

system.data 네임 스페이스 (ADONET)에는 관리되지 않는 리소스가 없습니다. 따라서 자신에게 특별한 것을 추가하지 않은 한 어떤 것도 폐기 할 필요가 없습니다.

Dispose 메서드 및 데이터 집합을 이해하고 있습니까? 권위자 Scott Allen의 의견이 있습니다.

실제로는 거의 혜택을 제공하지 않으므로 DataSet을 거의 처리하지 않습니다. “

따라서 현재 DataSet에서 Dispose를 호출해야 할 합당한 이유가 없습니다.


답변

업데이트 (2009 년 12 월 1 일) :

이 답변을 수정하고 원래 답변에 결함이 있음을 인정하고 싶습니다.

원래 분석 마무리가 필요한 물체에 적용됩니다. 정확하고 깊이있는 이해가 없으면 표면에서 관행을 받아들이지 않아야하는 시점이 있습니다.

그러나 DataSets, DataViews, DataTables 는 생성자에서 마무리를 억제합니다. 따라서 Dispose ()를 호출하면 명시 적으로 아무 작업도 수행되지 않습니다.

아마도 이것은 관리되지 않는 리소스가 없기 때문에 발생합니다. 따라서 MarshalByValueComponent 가 관리되지 않는 리소스를 허용 한다는 사실에도 불구하고 이러한 특정 구현에는 필요가 없으므로 마무리 작업을 포기할 수 없습니다.

.NET 작성자는 일반적으로 메모리를 가장 많이 차지하는 형식에 대한 마무리를 억제하기 위해주의를 기울여야합니다.이 형식은 일반적으로이 형식이 중요합니다.

그럼에도 불구하고 (약 8 년 전) .NET Framework를 시작한 이후로 이러한 세부 사항은 여전히 ​​문서화되지 않았다는 점이 놀랍습니다. 때때로 실망 스럽지만 우리가 일상적으로 사용하는 프레임 워크에 대한보다 완전한 이해를 제공합니다).

많은 독서 후, 여기 내 이해가 있습니다 :

객체가 마무리가 필요한 경우, 필요한 것보다 더 오래 메모리를 차지할 있습니다. 이유는 다음과 같습니다. a) 소멸자를 정의하는 유형 (또는 소멸자를 정의하는 유형에서 상속 된)은 최종적인 것으로 간주됩니다. b) 할당시 (생성자가 실행되기 전에) 포인터가 종료 큐에 배치됩니다. c) 종료 가능한 객체는 일반적으로
종료 종료는 객체의 헤더에서 비트를 해제하여 런타임에 종료자가 호출 될 필요가 없음을 나타냅니다 (FReachable 대기열을 이동할 필요는 없음). 종료 큐에 남아 있으며 SOS의! FinalizeQueue에서 계속보고합니다. 표준 1 대신 2 개의 수집 물 을 회수해야한다. d) 종료를 억제해도 종료 큐에서 오브젝트가 제거되지 않습니다 (SOS의! FinalizeQueue에서보고 됨)이 명령은 잘못된 것입니다. 종료 큐에 어떤 객체가 있는지 아는 것은 도움이되지 않습니다. 마무리 대기열에 어떤 객체가 있고 여전히 마무리가 필요한지 아는 것이 도움이 될 것입니다 (이에 대한 명령이 있습니까).

DataTable, DataSet, DataView 클래스는 모두 관리되지 않는 리소스를 (잠재적으로) 처리 할 수있는 최종화 가능 개체 인 MarshalByValueComponent에 뿌리를두고 있습니다.

  • DataTable, DataSet, DataView는 관리되지 않는 리소스를 도입하지 않기 때문에 생성자의 마무리를 억제합니다.
  • 이것은 비정상적인 패턴이지만 사용 후 발신자가 Dispose 호출에 대해 걱정할 필요가 없습니다.
  • 이는 DataTable이 다른 DataSet간에 공유 될 수 있다는 사실 때문에 DataSet이 하위 DataTable을 처리하지 않는 이유 일 수 있습니다.
  • 이는 또한 이러한 객체가 SOS의! FinalizeQueue 아래에 표시됨을 의미합니다.
  • 그러나 이러한 개체는 최종 수집 할 수없는 대응 물과 같이 단일 컬렉션 후에도 계속 재생 가능해야합니다.

4 (신규 참조) :

원래 답변 :

여기에 착륙 한 사람은 소음을 무시하고 아래의 참고 사항을주의 깊게 읽어야합니다.

의심 할 여지없이, Dispose Finalizable 객체에 대해 호출 해야 합니다.

데이터 테이블 최종화 가능합니다.

Dispose를 호출 하면 메모리 재생 속도가 크게 빨라집니다.

MarshalByValueComponent 는 Dispose ( ) 에서 GC.SuppressFinalize (this) 를 호출합니다. 이를 건너 뛰는 것은 메모리가 재생되기 전에 수백 개의 Gen0 컬렉션이 아닌 경우 수십을 기다려야한다는 것을 의미합니다.

마무리에 대한이 기본적인 이해를 통해 우리는 이미 매우 중요한 것들을 추론 할 수 있습니다.

첫째, 마무리가 필요한 객체는 그렇지 않은 객체보다 오래 산다. 사실, 그들은 훨씬 더 오래 살 수 있습니다. 예를 들어, gen2에있는 오브젝트를 마무리해야한다고 가정하십시오. 종료는 예약되지만 개체는 여전히 gen2에 있으므로 다음 gen2 수집이 발생할 때까지 다시 수집되지 않습니다. gen2 컬렉션은 비용이 많이 들기 때문에 매우 드물게 발생하기를 원하기 때문에 실제로는 오랜 시간이 걸릴 수 있습니다. 공간을 확보하기 전에 수백 개의 gen0 컬렉션이 아닌 경우 마무리가 필요한 오래된 개체는 수십을 기다려야 할 수도 있습니다.

둘째, 마무리가 필요한 물체는 담보 손상을 일으 킵니다. 내부 객체 포인터는 유효한 상태를 유지해야하므로, 최종화가 필요한 객체는 메모리에 남아있을뿐만 아니라 객체가 참조하는 모든 객체가 직간접 적으로 메모리에도 남아 있습니다. 거대한 개체 트리가 마무리가 필요한 단일 개체에 의해 고정 된 경우 방금 논의한 것처럼 전체 트리가 오래 지속될 수 있습니다. 따라서 파이널 라이저를 조금만 사용하고 가능한 한 적은 내부 객체 포인터가있는 객체에 배치하는 것이 중요합니다. 방금 제공 한 트리 예제에서 마무리가 필요한 리소스를 별도의 객체로 이동하고 트리의 루트에서 해당 객체에 대한 참조를 유지하면 문제를 쉽게 피할 수 있습니다.

마지막으로 마무리가 필요한 객체는 종료 자 스레드에 대한 작업을 만듭니다. 마무리 프로세스가 복잡한 프로세스 인 경우 유일하고 유일한 마무리 스레드는 해당 단계를 수행하는 데 많은 시간을 소비하므로 작업 백 로그가 발생하여 더 많은 개체가 마무리 대기 상태로 남아있을 수 있습니다. 따라서 마무리 작업이 가능한 한 적은 작업을 수행하는 것이 매우 중요합니다. 또한 모든 객체 포인터가 마무리하는 동안 유효한 상태로 유지되지만 해당 포인터가 이미 마무리 된 객체로 이어 지므로 유용하지 않을 수 있습니다. 포인터가 유효하더라도 종료 코드에서 객체 포인터를 따르는 것을 피하는 것이 일반적으로 가장 안전합니다. 안전하고 짧은 종료 코드 경로가 가장 좋습니다.

Gen2에서 100MB의 참조되지 않은 DataTable을 본 사람으로부터 가져옵니다.이 스레드의 답변에 의해 매우 중요하고 완전히 놓친 것입니다.

참고 문헌 :

1http :
//msdn.microsoft.com/en-us/library/ms973837.aspx

2http :
//vineetgupta.spaces.live.com/blog/cns!8DE4BDC896BEE1AD!1104.entry
http://www.dotnetfunda.com/articles/article524-net-best-practice-no-2-improve-garbage -collector-performance-using-finalizedispose-pattern.aspx

3http :
//codeidol.com/csharp/net-framework/Inside-the-CLR/Automatic-Memory-Management/


답변

유용한 것이 있다고 가정하고 current에 아무 것도 없어도 Dispose를 호출해야합니다. NET Framework의 구현에서는 향후 버전에서 이러한 방식을 유지하여 비효율적 인 리소스 사용을 보장하지는 않습니다.


답변

개체에 관리되지 않는 리소스가없는 경우라도 폐기하면 개체 그래프를 손상시켜 GC에 도움이 될 수 있습니다. 일반적으로 객체가 IDisposable을 구현하면 Dispose ()를 호출해야합니다.

Dispose ()가 실제로 무언가를 수행하는지 여부는 주어진 클래스에 따라 다릅니다. DataSet의 경우 Dispose () 구현은 MarshalByValueComponent에서 상속됩니다. 컨테이너에서 자신을 제거하고 Disposed 이벤트를 호출합니다. 소스 코드는 다음과 같습니다 (.NET 리플렉터로 분해됨).

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        lock (this)
        {
            if ((this.site != null) && (this.site.Container != null))
            {
                this.site.Container.Remove(this);
            }
            if (this.events != null)
            {
                EventHandler handler = (EventHandler) this.events[EventDisposed];
                if (handler != null)
                {
                    handler(this, EventArgs.Empty);
                }
            }
        }
    }
}


답변

DataTable을 직접 작성합니까? DataSet.Tables에서와 같이 모든 Object의 자식을 반복하는 것은 일반적으로 필요하지 않기 때문에 부모의 모든 자식 멤버를 처리하는 것이 부모의 작업이기 때문입니다.

일반적으로 규칙은 다음과 같습니다. 규칙을 생성하고 IDisposable을 구현하는 경우 폐기하십시오. 작성하지 않은 경우 처리하지 마십시오. 이는 상위 오브젝트의 작업입니다. 그러나 각 개체에는 특별한 규칙이있을 수 있습니다. 설명서를 확인하십시오.

.net 3.5의 경우 명시 적으로 “더 이상 사용하지 않을 때는 폐기하십시오”라고 표시되어 있습니다.


답변

객체가 IDisposeable을 구현할 때마다 dispose를 호출합니다. 이유가 있습니다.

데이터 세트는 거대한 메모리 호그 일 수 있습니다. 정리 표시가 빠를수록 빠를수록 좋습니다.

최신 정보

이 질문에 답한 지 5 년이 지났습니다. 나는 여전히 내 대답에 동의합니다. dispose 메서드가 있으면 개체를 다룰 때 호출해야합니다. IDispose 인터페이스가 이유로 구현되었습니다.


답변

이 질문의 의도 또는 컨텍스트가 실제로 가비지 콜렉션 인 경우 데이터 세트 및 데이터 테이블을 명시 적으로 null로 설정하거나 using 키워드를 사용하여 범위를 벗어날 수 있습니다. Tetraneutron이 이전에 말한 것처럼 처분은별로하지 않습니다. GC는 더 이상 참조되지 않는 데이터 세트 객체와 범위를 벗어난 데이터 세트 객체를 수집합니다.

나는 정말로 투표를 거절 한 사람들이 답을 내리기 전에 실제로 의견을 쓰길 바랍니다.