2011-02-17 3 views
3

개체의 이벤트에 무차별 적으로 처리기를 추가 할 때, 같은 처리기를 원하는만큼 여러 번 이벤트에 첨부 할 수 있다는 것을 알게되었습니다. 즉, 핸들러는 연결될 때마다 한 번 호출됩니다..NET에서 이벤트 처리기로 작업하기

  • 핸들러 객체의 이벤트에 추가 된 어떤 볼 수있는 방법이 있나요 :

    나는이 일을 궁금하네요?

  • 이벤트에서 모든 처리기를 제거 할 수 있습니까?
  • 이벤트와 핸들러 사이의 상관 관계는 어디에 저장됩니까? 이벤트가 C# 이벤트 키워드로 표시되어
+1

지우기 처리기 : http://stackoverflow.com/questions/91778/how-to-remove-all-event-handlers-from-a-control –

+0

이것은 좋은 코딩 원칙을 위반하는 * 매우 * 강한 것입니다. * event * 키워드가 처음 존재하는 이유 중 하나는 매우 효과적입니다. –

+0

@ 한스 패 탄트 (Hans Passant) : 이벤트 구독 목록을 없애기 위해 폐기 된 개체에 대해서는 좋은 생각이라고 생각합니다. 그렇지 않으면 폐기 된 객체에 대한 실시간 참조가 있으면 객체의 모든 이전 구독자도 살아있게됩니다. 더 이상 이벤트를 제기하지 않을 처분 된 객체가 구독 목록을 죽이지 않아야하는 이유가 있습니까? – supercat

답변

2

경우 가입자을 볼 수있는 객체 외부에서 방법은 없습니다 - 필요한 정보를 바로 볼 수 없습니다.

내부적으로는 복잡 할 수도 있지만 구현의 세부 사항에 따라 달라질 수 있지만 (아직 완료되지는 않았습니다.) 수행 할 수 있습니다.

유용 할 수있는 해결 방법은 처리기를 제거하는 것입니다. 예외는 발생하지 않습니다.

그래서이 코드는 유효합니다 : 이미 이벤트에 가입하는 경우

myConnection.Closing -= ConnectionClosingHandler; 
myConnection.Closing += ConnectionClosingHandler; 

는, 첫 번째 줄은 구독을 제거합니다.
이 아닌 경우 이미에 가입하면 첫 번째 줄에는 아무런 변화가 없습니다.

두 번째 줄은 새 구독을 연결하여 여러 번 알림을받지 않습니다.

public event PropertyChangedEventHandler Changed; 

컴파일러는 모든 가입자를 저장 형 PropertyChangedEventHandler의 멤버 변수를 만듭니다 당신이 정상 이벤트를 선언 할 때

는 마지막 글 머리에 대답합니다. 원하는 경우 저장을 대신 할 수 : 구독을 수정하는 -=+=의 사용은 문법 설탕이
public event PropertyChangedEventHandler Changed 
{ 
    add { ... } 
    remove { ... } 
} 

하지

- 대의원은 불변이며, 추가 또는 핸들러를 제거 할 때 새로운 인스턴스가 반환된다 . 이 작동 방식에 대한 자세한 내용은 DelegateMulticastDelegate (두 MSDN 링크)을 참조하십시오.

1

이벤트와 핸들러 간의 상관 관계는 이벤트 자체에 저장됩니다. 이벤트에 액세스하면이 정보가 실제로 메소드 그룹에 복사됩니다. 즉,이 말을하는 거 야 이유는 다음과 같습니다

var onclick = Click; 
if (onclick != null) onclick(); 

나는 Click 이벤트를 액세스 두 번이 아니라 중간 onclick 변수를 사용하는 것보다, 내가 어떤 이벤트가 두 번 복사 할 발생했을 경우. 또한 다중 스레드 시나리오에서 누군가가 Click != null을 확인하고 처리기를 호출하는 사이에 처리기를 제거하면 예외가 발생할 수 있습니다.당신이 이미 제거 할 핸들러 알고있는 경우

, 그것은 그 핸들러 제거하기 쉽습니다 : 객체의 이벤트에 추가 된 각 처리기에 대한 몇 가지 기본 정보를 얻을 수있는 방법이 있습니다

EventHandler handler1 = (sender, e) => Console.WriteLine("test"); 
Click += handler1; 
Click -= handler1; 

을, GetInvocationList를 통해 그러나

foreach(var handler in Click.GetInvocationList()) 
    Console.WriteLine(handler.Method.ToString()); 

, 당신이 밖으로 얻는 정보는 Delegate 객체의 형태이다. 호출 될 수 있습니다 (하나의 핸들러에서 던져진 예외를 catch하고 나머지 핸들러를 계속 호출하려는 경우 유용 할 수 있지만 C#은이 정보를 기반으로 이벤트에서 핸들러를 쉽게 제거 할 수있는 방법을 제공하지 않습니다 . How to remove all event handlers from a control의 답변 중 일부는 Reflection을 사용하여 Visual Basic의 RemoveHandler 명령을 사용할 수 있음을 나타냅니다.

관련 문제