[.net] 닫고 처리-전화?

스레드를 읽었 습니까? SqlCommand.Dispose가 충분합니까? 은 WCF 서비스 닫고 폐기 나는 그것이 문제가 않습니다 같은도록 SqlConnection 또는 스트림 클래스에서 상속 여러 클래스 중 하나의 클래스에 대한 궁금하면 I 가까운 폐기하는 대신 닫기?



답변

이 상황을 명확히하고 싶습니다.

Microsoft 지침에 따르면 Close적절한 방법 을 제공하는 것이 좋습니다 . 다음프레임 워크 디자인 가이드 라인 에서 인용 한 내용입니다.

해당 지역의 표준 용어가 밀접한 경우 Close()에 추가하여 방법을 제공하십시오 Dispose(). 그렇게 할 때 Close구현을 동일하게 만드는 것이 중요합니다 Dispose

대부분의 경우 CloseDispose방법은 동일합니다. 주요 차이점 사이 CloseDispose의 경우 SqlConnectionObject이다

응용 프로그램은 Close여러 번 호출 할 수 있습니다 . 예외는 생성되지 않습니다.

Dispose메소드
를 호출하면 SqlConnection객체 상태가 재설정됩니다. 폐기 된 SqlConnection
객체에서 메소드를 호출하려고하면 예외가 발생합니다.

그것은 말했다 :

  • 연결 개체를 한 번 사용하는 경우을 사용하십시오 Dispose.
  • 연결 개체를 재사용해야하는 경우 Close방법을 사용하십시오 .

답변

평소와 같이 대답은 다음과 같습니다. 다른 수업 IDisposable은 다른 방식으로 구현 되며 필요한 연구를 수행하는 것은 당신에게 달려 있습니다.

가능한 SqlClient한 권장되는 방법은 다음을 수행하는 것입니다.

using (SqlConnection conn = /* Create new instance using your favorite method */)
{
    conn.Open();
    using (SqlCommand command = /* Create new instance using your favorite method */)
    {
        // Do work
    }
    conn.Close(); // Optional
}

당신은 해야 호출 할 Dispose(또는 Close연결에 *)! 마십시오 하지 가비지 수집기가 연결을 정리할 때까지 기다립니다,이 (적어도) 다음 GC주기까지 풀에서 연결을 묶어 것입니다. 호출하면 호출 할 Dispose필요가 없으며 Close, using구문을 Dispose올바르게 처리하기 쉽기 때문에 호출 할 이유가 없습니다 Close.

연결은 자동으로 풀링 되며 연결에서 Dispose/ Close를 호출 해도 물리적으로 연결이 닫히지 않습니다 (정상적인 상황에서). 자신의 풀링을 구현하지 마십시오. SqlClient풀에서 검색 될 때 연결에서 정리를 수행합니다 (예 : 데이터베이스 컨텍스트 및 연결 옵션 복원).

*를 호출 Close하는 경우 예외 안전 방식 (예 : catch 또는 finally 블록)으로 수행해야합니다.


답변

Dispose ()를 호출해야합니다!

Dispose ()는 개발자가 호출하고 가비지 콜렉터는 Finalize ()를 호출합니다. 객체에서 Dispose ()를 호출하지 않으면 사용 된 관리되지 않는 리소스는 가비지 수집기가 돌아와서 마무리 할 때까지 (그리고 누가 언제 일어날 지 알 때까지) 폐기되지 않습니다.

이 시나리오를 비 결정적 마무리라고하며 .net 개발자에게 일반적인 함정입니다. IDisposable을 구현하는 객체로 작업하는 경우 Dispose ()를 호출하십시오!

http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last

일부 개체에서 Disponse ()를 호출하고 연결에서 Close ()를 호출하거나 파일 핸들을 닫는 인스턴스가 많을 수도 있지만 (SqlConnection과 같이) Dispose ()를 호출하는 것이 가장 좋습니다. 가까운 시일 내에 객체를 재사용 할 계획이 아니라면.


답변

를 들어 SqlConnection, 연결 자체의 관점에서, 그들은 동일합니다. Reflector에 따르면, Dispose()호출 Close()은 몇 가지 추가 메모리 프리 작업을 수행 할뿐 아니라 대부분 멤버를 null로 설정하여 호출합니다 .

Stream의 경우 실제로 동일합니다. Stream.Dispose()간단히 Close ()를 호출합니다.


답변

이것은 빠른 조언이 긴 대답이되었습니다. 죄송합니다.

타일러가 그의 멋진 답변에서 지적했듯이 호출 Dispose()은 훌륭한 프로그래밍 관행입니다. 이 방법은 필요한 모든 자원 확보를 “집결”하여 불필요한 공개 자원이 없기 때문입니다. 예를 들어, 파일에 텍스트를 쓰고 파일을 닫지 못한 경우 (자원을 비우는 경우) 해당 파일은 열린 상태로 유지되며 GC가 돌아와서 필요한 것을 수행 할 때까지 다른 사람이 파일에 쓸 수 없습니다. 끝난.

이제 어떤 경우에는을 ( StreamWriter.Close()를) 재정의하는 것과 같이 처리하는 클래스에 대해 더 구체적인 “완료”메서드 가 있습니다 TextWriter.Close(). 실제로 이들은 일반적으로 상황에 더 적합합니다. Close()예를 들어 StreamWriter ‘s Dispose()는 객체를 보내기 전에 스트림과 기본 인코더를 플러시 합니다! 멋있는!

그러나 MSDN을 살펴보면 Microsoft조차도 수많은 클로저 및 디스 포저로 인해 혼란 스러울 수 있습니다. 예를 들어, 이 웹 페이지 에서 일부 예 Close()에서 암시 적 전에 호출됩니다 Dispose()( 암시 적 이유를 이해하지 못하는 경우 문 사용 참조 ). 특히 웹 페이지에서는 신경 쓰지 않습니다. 왜 그런가요? 나도 당황했다.

내가 생각한 이유는 (이것은 독창적 인 연구 이며 내가 틀렸다면 분명히 명성을 잃을 수 있음을 강조합니다) Close()자원이 열려있는 동안 예외가 발생하는 동시에 실패 Dispose()할 수 있기 때문 입니다. 어떤 이유 A는 Dispose()항상 보호해야 Close()호출 (말장난에 대한 유감을).

MyResource r = new MyResource();

try {
  r.Write(new Whatever());

  r.Close()
finally {
  r.Dispose();
}

그리고 네, 마이크로 소프트가 그 한 가지 예에 착수했다고 생각합니다. 아마도 타임 스탬프가 파일로 플러시되지 않을 것입니다.

내일 이전 코드를 수정하고 있습니다.

편집 : 죄송합니다 브래넌, 나는 당신의 대답에 대해 언급 할 수는 없지만 확신이 호출에 좋은 아이디어이다 있습니다 Close()A의 finally블록? 그것의 예외는 블록의 나머지 부분을 망칠 수 있다고 생각합니다.

Brannon ‘s에 대한 답변 : 훌륭합니다. Close()실제로 필요할 때 호출하는 것을 잊지 마십시오 (예 : 스트림을 다룰 때-.NET의 SQL 연결에 대해 잘 모름).


답변

iDisposable로 타입 캐스트하고 dispose를 호출하십시오. 함수의 이름에 관계없이 “iDisposable.Dispose”를 구현하도록 구성된 모든 메소드를 호출합니다.


답변

일반적으로 Close (), Abort () 및 Dispose ()에서 문제가 발생하지만 차이점을 알려 드리겠습니다.

1) ABORT :-중단을 호출하면 클라이언트가 서버에 알리지 않고 연결을 삭제하므로 서버가 일정 시간 (약 1 분) 동안 기다릴 수 있으므로 사용하지 않는 것이 좋습니다. 대량 요청이있는 경우 제한된 연결 풀에 시간 초과가 발생할 수 있으므로 abort ()를 사용할 수 없습니다.

2) 닫기 :-닫기는 연결을 닫을 때 서버를 호출하고 서버가 그 쪽에서 닫는 것을 승인하기 때문에 연결을 닫는 매우 좋은 방법입니다.

여기에 한 가지 더 있습니다. 어떤 경우에는 오류가 발생하면 해당 Connection.close ()에 코드를 작성하는 것이 좋은 방법이 아닙니다. 그 당시 통신 상태에 오류가 있기 때문입니다.

3) 처리 :-폐쇄 유형 중 하나이지만 연결을 닫은 후에는 다시 열 수 없습니다.

이 방법으로 시도하십시오.

private void CloseConnection(Client client)
    {
        if (client != null && client.State == CommunicationState.Opened)
        {
            client.Close();
        }
        else
        {
            client.Abort();
        }
    }