C#: 스레드 안전 이벤트
-
10-07-2019 - |
문제
구현이 스레드-안전보다 낮습니까? 내가 놓친 것이 아니라면? 내가 가야할까요 volatile
어딘가에 키워드? 또는 어딘가에 잠금 OnProcessingCompleted
방법? 그렇다면 어디?
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);
}
}
메모: 개인 이벤트와 명시 적 인터페이스를 가진 이유는 추상적 인 기본 클래스이기 때문입니다. 그리고 상속 된 수업은 해당 이벤트와 직접 아무것도하지 않아야합니다. 클래스 래퍼를 추가하여 더 명확하게 =)
해결책
개인이 필요하지 않습니다 ProcessCompleted
회원이 될 수 있습니다 event
- 단지 필드 일 수 있습니다. private EventHandler<ProcessCompletedEventArgs> ProcessCompleted;
- 클래스 내부에서는 항상 현장으로 바로갑니다. event
어쨌든 물건이 사라집니다.
명시 적 잠금 객체로 보여준 접근 방식은 많이 필드와 같은 이벤트를 갖는 것보다 더 많은 스레드 안전 public event EventHandler<ProcessCompletedEventArgs> ProcessCompleted;
- 유일한 차이점은 당신이 "이것"을 잠그지 않는다는 것입니다 (좋은 일입니다 - 당신은 이상적으로 잠그는 것을 피하십시오 this
) .. "핸들러 변수"접근법은 올바른 방법이지만 여전히 당신이 알아야 할 부작용.
다른 팁
핸들러를 가져올 때도 잠겨 있어야합니다. 그렇지 않으면 최신 값이 없을 수도 있습니다.
protected void OnProcessingCompleted(ProcessCompletedEventArgs e)
{
EventHandler<ProcessCompletedEventArgs> handler;
lock (completedEventLock)
{
handler = ProcessCompleted;
}
if (handler != null)
handler(this, e);
}
이것에 주목하십시오 그렇지 않습니다 우리가 결정한 경주 조건을 방지합니다. 그 다음에 하나의 핸들러가 구독되지 않은. 우리는 그것을 포함하는 멀티 캐스트 대의원을 가져 왔기 때문에 여전히 호출됩니다. handler
변하기 쉬운.
핸들러 자체가 더 이상 부르지 않아야한다는 것을 알리는 것 외에는 이것에 대해 할 수있는 일이 많지 않습니다.
그렇지 않은 것이 틀림없이 낫습니다 노력하다 이벤트를 스레드 - 안전 - 구독이 뿐 이벤트를 제기 할 스레드의 변화.