2009-06-24 6 views
5

구현이 스레드로부터 안전합니까? 내가 뭘 놓치지 않으면? 어딘가에서 volatile 개의 키워드를 사용해야합니까? 또는 OnProcessingCompleted 방법의 어딘가에 잠금 장치가 있습니까? 그렇다면 어디에서? C# : 스레드로부터 안전한 이벤트

public abstract class ProcessBase : IProcess 
{ 
    private readonly object completedEventLock = new object(); 

    private event EventHandler<ProcessCompletedEventArgs> ProcessCompleted; 

    event EventHandler<ProcessCompletedEventArgs> IProcess.ProcessCompleted 
    { 
     add 
     { 
      lock (completedEventLock) 
       ProcessCompleted += value; 
     } 
     remove 
     { 
      lock (completedEventLock) 
       ProcessCompleted -= value; 
     } 
    } 

    protected void OnProcessingCompleted(ProcessCompletedEventArgs e) 
    { 
     EventHandler<ProcessCompletedEventArgs> handler = ProcessCompleted; 
     if (handler != null) 
      handler(this, e); 
    } 
} 


참고 :이 추상 기본 클래스이기 때문에 개인 이벤트 및 명시 적 인터페이스 물건을 왜 이유가있다. 그리고 그것으로부터 상속받은 클래스는 그 이벤트에 직접적으로 어떤 것도해서는 안됩니다.

+0

(댓글에 대한 답글) –

답변

4

event 될 수있는 개인 ProcessCompleted 구성원에 대한 필요가 없습니다) = 더 명확 있도록 클래스 래퍼를 추가 - 그냥 필드 수 : - 항상 현장에 바로가는 클래스 내부 private EventHandler<ProcessCompletedEventArgs> ProcessCompleted; , 따라서 어쨌든 event 물건이 손실됩니다.

당신이 명시 적으로 락 객체로 표시 한 접근 방식은 아니다 많은 스레드 안전 그냥 필드와 같은 이벤트를하는 것보다 더 (즉 public event EventHandler<ProcessCompletedEventArgs> ProcessCompleted; - 유일한 차이점은 "이"고정되지 않은 것입니다 (좋은 일이있는 - 당신은 이상적으로 피하기 this에 고정한다). 당신이 너무 핸들러를 가져올 때 있습니다 .. "핸들러 변수"접근 방식은 바로 하나이지만, 여전히 side-effects you should be aware of있다

+0

개인 이벤트 처리기와 명시 적 이벤트 항목을 사용하는 이유가 추가되었습니다. 그것은 여전히 ​​필요하지 않습니까? 그 차이가 무엇을 의미합니까? 공개 이벤트 EventHandler SomeEvent 자동으로 잠금을 수행합니까? – Svish

+2

예; 필드와 같은 이벤트 (즉, 명시 적 추가/제거가없는 이벤트)에는 내장 된 잠금이 있습니다 (this). 언어 사양 (MS 버전)에서 10.8.1 참조; 그러나이 클래스 내부의 코드는 무시됩니다. http://marcgravell.blogspot.com/2009/02/fun-with-field-like-events.html을 참조하십시오. 따라서 * private * 이벤트처럼 추가/제거 (따라서 잠금)는 사용되지 않습니다. 명시 적 인터페이스 구현의 경우 코드가 좋으며 수행 한 자물쇠를 직접 추가해야하며 "잠금 (this)"보다 틀림없이 * 더 나은 *을 추가해야합니다. 그것에 붙여라 ;-p –

+0

alrighty =) – Svish

5

당신은 잠글 필요 그렇지 않으면 최신 값을 가질 수 없습니다.

protected void OnProcessingCompleted(ProcessCompletedEventArgs e) 
{ 
    EventHandler<ProcessCompletedEventArgs> handler; 
    lock (completedEventLock) 
    { 
     handler = ProcessCompleted; 
    } 
    if (handler != null) 
     handler(this, e); 
} 

이 아니며, 처리기 집합을 실행하기로 결정한 경쟁 조건을 방지하고 다음 처리기를 구독 취소 한 것에 유의하십시오. 변수를 포함하는 멀티 캐스트 대리자를 handler 변수로 가져 왔으므로 여전히 호출됩니다.

처리기 자체가 더 이상 호출되면 안된다는 것을 인식하는 것 외에는 할 수있는 일이 많지 않습니다.

그냥하지 이벤트가 스레드 안전 할을 시도 틀림없이 더 나은 - 지정이 가입해야 이벤트를 올릴 것이다 스레드에서 변화.

+0

확실한, 자물쇠가 필요한가요? 델리게이트는 불변이고 assignmend는 원자 적 연산이므로 아무런 잠금도 필요하지 않습니다. – TcKs

+0

게시물에 대한 내 의견보기. 스레드로부터 안전하게하려면 반드시 잠금이 필요합니다. –

+0

예, "추가"및 "제거"의 잠금이 필요합니다. 하지만 "OnProcessingCompleted"에서 "잠금"을 사용하면 어떤 이점이 있습니까? – TcKs

관련 문제