이 질문에는 이미 답변이 있습니다.
그래서 나는 그 사건을 직접 읽지 않고 읽었습니다.
if (SomeEvent != null)
SomeEvent(this, null);
나는해야한다.
SomeEventHandler temp = SomeEvent;
if (temp != null)
temp(this, null);
이게 왜 그렇게? 두 번째 버전은 어떻게 스레드로부터 안전합니까? 가장 좋은 방법은 무엇입니까?
이벤트는 실제로 대리자 목록에 대한 통사론적인 설탕입니다. 이벤트를 호출하면 실제로이 목록을 반복하고 전달한 매개 변수로 각 대리자를 호출합니다.
스레드의 문제점은 가입 / 탈퇴로이 컬렉션에 항목을 추가하거나 제거 할 수 있다는 것입니다. 그들이 컬렉션을 반복하는 동안이 작업을 수행하면 문제가 발생할 것입니다 (예외가 발생한다고 생각합니다)
목록은 반복하기 전에 목록을 복사하므로 목록 변경에 대해 보호됩니다.
참고 : 그러나 구독 취소 한 후에도 리스너를 호출 할 수 있으므로 리스너 코드에서 리스너를 처리해야합니다.
IMO, 다른 답변은 하나의 주요 세부 사항을 놓치게됩니다. 대표자 (따라서 이벤트)는불변의. 이것의 중요성은 이벤트 핸들러를 구독하거나 구독 취소하는 것입니다하지 않는다간단히 목록에 추가 / 제거 - 오히려 그것을대체하다목록에 추가 항목이있는 새 목록이 표시됩니다.
참조가 원자 적이므로이 시점에서 참조하는 것은 다음을 의미합니다.
var handler = SomeEvent;
너는 이제엄격한다음 picosecond에서 다른 스레드가 구독 취소 한 경우에도 변경할 수없는 인스턴스입니다 (실제의될 이벤트 필드null
).
그래서 당신은 null을 테스트하고 그것을 호출하고, 모든 것이 잘됩니다. 당연히 거기주의하십시오아직도사건의 혼란스러운 시나리오높인피코 세컨드를 구독 취소했다고 생각하는 객체에!
lock
) 영역 (구형 컴파일러) - Marc Gravell♦