문제

나는 단지 페이지를 읽고 있었다 이벤트 MSDN에서, 나는 나를 당황하게하는 예제 코드 스 니펫을 발견했습니다.

문제의 코드는 다음과 같습니다.

// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;

나는 코드의 의도를 이해하지만, 그 특정 라인이 어떻게 사본을 만들고 있는지 알지 못합니다. 그것이하는 일은 복사하는 것입니다 참조; 실제로 대의원 인스턴스의 깊은 사본을 만드는 것은 아닙니다. 따라서 실제로 인종 조건을 전혀 방지하지는 않습니다.

여기서 명백한 것을 놓치고 있습니까?

도움이 되었습니까?

해결책

대의원은 불변이기 때문에 해당 코드에서 얻은 참조는 변경되지 않도록 보장됩니다. NULL Check 후 사용자가 구독하거나 구독을하지 않으면 새 대표가 생성되어 이벤트로 설정됩니다. 그러나 완전히 다른 객체에 대한 언급이 있고 그것을 호출하기 때문에, 당신은 그것이 널이라는 것에 대해 걱정할 필요가 없습니다.

다른 팁

당신이 올바른지; 참조를 복사하고 있습니다.

그러나 대표단은 불변입니다. 이벤트에 핸들러를 추가하면 현재 핸들러와 새로운 대의원이 생성되어 현재 처리기와 새로운 핸들러를 결합한 다음 필드에 할당됩니다.

필드가 참조중인 대의원 인스턴스는 변경 될 수 없으므로 레이스 조건을 피합니다.

에릭 립퍼트 이미 이것을 매우 상세하게 다루었습니다 게시하다.

이것도 MSDN에서 나온 것입니다 ..

"대의원의 호출 목록은 순서 대의 대의원 세트입니다. 목록은 대의원이 나타내는 방법 중 하나를 호출합니다. 호출 목록에는 중복 메소드가 포함될 수 있습니다. 호출하는 동안 메소드는 호출 목록에 나타나는 순서로 호출됩니다. 대의원은 호출 목록에서 모든 방법을 호출하려고 시도합니다. 호출 목록에 나타날 때마다 한 번의 복제물이 호출됩니다. 대표단은 불변입니다. 일단 생성되면 대의원의 호출 목록은 변경되지 않습니다."

if (whatever != null) whatever(); 그것을 보장하는 것 같습니다 whatever 언제든지는 안됩니다 whatever() 호출되지만 실제로는 스레드 시나리오에서는 보장하지 않습니다. 다른 스레드가 설정 될 수 있습니다 whatever = null 수표와 통화 사이.

Foo temp = whatever;
if (temp != null) temp();

이 코드는 귀무인 단위의 가능성을 제거합니다. temp 로컬이므로 다른 스레드로 수정되지 않습니다. 따라서 인종 조건을 방지합니다. 그래도 모든 관련 인종 조건을 방지하지는 않습니다. 에릭 립퍼트는 더 정교합니다 코드의 다른 문제에 대한 논의.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top