2014-09-19 3 views
0

System.Windows.Forms.Control에서 Dispose()으로 전화하면 모든 이벤트 등록이 자동으로 제거됩니까?`Control.Dispose()`는 모든 이벤트 등록을 제거합니까?

var button = new Button(); 
button.Click += someObject.clickHandler; 
// ... 
button.Dispose(); 

또는 같은, 내가 명시 적으로 이벤트 핸들러의 등록을 취소해야합니까 :

그래서 예를 들어, 다음과 같은 충분한 명시 적으로 이벤트 핸들러를 제거하지 않습니다 Dispose()를 호출

var button = new Button(); 
button.Click += someObject.clickHandler; 
// ... 
button.Click -= someObject.clickHandler; 
button.Dispose(); 
+1

Annoyingly,'Component' (따라서'Control')가 (EventHandlerList를 통해) 대부분의 이벤트에 사용하는 모델은 실제로 이것을 매우 달성 할 수있었습니다. 그들이 이것을하지 않기로 결정한 것은 흥미 롭습니다. 그들이 처리해야 할 것은'Dispose (bool disposing) '의 끝에'events' 필드를'null'로 설정하는 것입니다. –

+0

예,'Component'에서'EventHandlerList' 필드를 보았고, 모든 이벤트 처리기를 구독 취소하기 위해'Dispose (bool) '에 있습니다.하지만 문서에 언급되어 있지 않습니다. 그래서 내가 여기 묻어야 만했습니다 ... 정말로 짜증나게합니다! –

답변

1

아니요. 핸들러를 직접 제거해야합니다. 간단한 테스트로 증명할 수 있습니다.

protected override void OnLoad(EventArgs e) 
{ 
    base.OnLoad(e); 

    var button = new Button(); 
    button.Click += button_Click; 

    //Some code 
    button.Dispose(); 
    button.PerformClick();//Simulate a click event 
} 

void button_Click(object sender, EventArgs e) 
{ 
    MessageBox.Show("Oops! Still alive?"); 
} 

위의 코드를 실행하면 MessageBox에 "Oops, Still alive?"라는 메시지가 표시됩니다. 즉 핸들러는 이 제거되지 않았 음을 의미합니다. DisposeControl 일 때도이 표시됩니다.

가비지 수집에 어떤 영향이 있는지 보려면 Marc's answer here을 참조하십시오.

2

, 그러나 더 이상 전송되지 않는 이벤트가 발생합니다. 가비지 수집기가 button에서 메모리를 회수하면 짝수 번째 등록이 최종적으로 제거됩니다. 이 경우

var button = new Button(); 
otherObject.SomeEvent += button.HandleSomeEvent; 
// ... 
button.Dispose(); 

, 등록 된 이벤트 핸들러가 실제로 쓰레기를 수집하기에서 button을 방지 할 수 있습니다 : button 다른 개체에서 이벤트를 나열 할 때 고려해야 할

더 중요한 상황이다. 이러한 상황이 코드에 적용되는 경우 Dispose() 메서드에서 관련 이벤트 리스너를 제거하거나 약한 이벤트 리스너 패턴을 사용하여 가비지 수집기에서 해당 핸들러를 정리할 수 있도록해야합니다.