이벤트 처리기가 가비지 수집을 중지합니까?


183

다음 코드가있는 경우 :

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass = null;

pClass는 가비지 수집됩니까? 아니면 이벤트가 발생할 때마다 이벤트가 계속 발생합니까? 가비지 수집을 허용하려면 다음을 수행해야합니까?

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass.MyEvent -= MyFunction;
pClass = null;

11
가비지 수집이 발생하지 않도록 가벼운 이벤트 / 약한 이벤트 패턴에 익숙해지는 것이 좋습니다. 이 주제에 대한 좋은 SO 부트 스트랩은 stackoverflow.com/questions/185931/…
fostandy

20
후손에 대한 참고 사항 : 참조를 null로 설정하면 참조 범위를 한 줄씩 확장하여 가비지 수집기를 지연시킵니다. .NET은 VB6이 아닙니다.
John Saunders

답변:


207

"pClass가 가비지 수집됩니까?"라는 특정 질문의 경우 : 이벤트 구독은 pClass (게시자)의 콜렉션에 영향을 미치지 않습니다.

일반적으로 GC (특히 대상)의 경우 : MyFunction이 정적인지 인스턴스 기반인지에 따라 다릅니다.

인스턴스 메소드에 대한 위임 (예 : 이벤트 구독)에는 인스턴스에 대한 참조가 포함됩니다. 예, 이벤트 구독은 GC를 방해합니다. 그러나 이벤트를 게시하는 객체 (위의 pClass)를 수집 할 수있게되면 문제가되지 않습니다.

이것은 단방향입니다. 즉, 우리가 가지고 있다면 :

publisher.SomeEvent += target.SomeHandler;

"publisher"는 "target"을 유지하지만 "target"은 "publisher"를 유지하지 않습니다.

pNo가 어쨌든 수집 될 경우 리스너를 구독 취소 할 필요가 없습니다. pClass는 (더 이상의 MyFunction와 인스턴스 이상) 수명이 긴 경우가 있으므로 그러나, 다음 pClass는 살아 해당 인스턴스를 유지할 수있는 것이 대상이 수집하려면 취소하는 것이 필요합니다.

그러나 이러한 이유로 정적 이벤트는 인스턴스 기반 핸들러와 함께 사용할 때 매우 위험합니다.


6
질문이 "pClass가 가비지 수집됩니까?"라면, "... 여부에 따라 다릅니다"라는 대답이 실제로 정확하지 않습니다. Marc 자신이 더 자세히 언급했듯이 아무것도 의존하지 않습니다.
Tor Haugen

@Tor-충분히 공평-나는 명확히 할 것이다
Marc Gravell

이벤트 구독 대리자는 한 가지 방법 만 가리 키지 만 이벤트를 구독 할 때 구독을 취소하려는 가입자에게는 게시자에 대한 참조 형식이 필요합니다. 그것은 WeakReference좋은 아이디어 일 수 있지만 때로는 그렇지 않을 수도 있습니다.
supercat

질문의 나머지 절반 (요청하지 않은)도 다루기 때문에 훌륭한 답변입니다. 게시자구독자 가 GC를받지 못하게합니다.
Bob Sammers 2016 년

예. @BobSammers가 말했듯이 Form / Window와 같은 짧은 수명 인스턴스가 예를 들어 데이터를 제공하는 Singleton과 같은 수명이 긴 서비스를 구독하는 경우 실제로 문제가 될 수 있습니다. Singleton은 참조를 유지합니다 따라서 객체가 언로드되었다고 생각 되더라도 메모리에 메모리가 유지됩니다! 따라서 이벤트를 사용할 때는 매우주의해야합니다. 우리는 우리의 큰 소프트웨어에 대한 이벤트를 남용했으며 나중에 해결하기가 매우 어렵습니다.
Elo

9

예, pClass는 가비지 수집됩니다. 이벤트 구독은 pClass에 대한 참조가 있음을 의미하지 않습니다.

따라서 pClass를 가비지 수집하기 위해 핸들러를 분리하지 않아도됩니다.


8

메모리 조각이 더 이상 참조되지 않는 순간 가비지 수집 대상이됩니다. 클래스의 인스턴스가 범위를 벗어나면 더 이상 프로그램에서 참조하지 않습니다. 더 이상 사용되지 않으므로 안전하게 수집 할 수 있습니다.

확실하지 않다면 무언가를 수집 할 것인지 스스로에게 다음과 같은 질문을하십시오. 이벤트 핸들러는 다른 방법이 아닌 객체 인스턴스에 의해 참조됩니다.


0

pClass가비지 수집됩니다. 위의 코드 스 니펫을 다른 클래스 내에있을 경우 설정하지 않은 경우, 그 클래스의 인스턴스가 삭제되지 않을 수 있습니다 pClassnull.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.