대리자 멤버 변수가있는 클래스 인스턴스가 있고 여러 스레드가 해당 대리자를 호출하면 (장기 실행 메서드를 가리킨다 고 가정) 경합 문제가 있습니까?C# 대리자가 스레드로부터 안전합니까?
대리자를 잠글 필요가 있습니까? 아니면 각 스레드가 자체 호출 스택을 가져 오기 때문에 각 스레드가 대리자가 가리키는 메서드를 호출하는 것이 안전합니까?
대리자 멤버 변수가있는 클래스 인스턴스가 있고 여러 스레드가 해당 대리자를 호출하면 (장기 실행 메서드를 가리킨다 고 가정) 경합 문제가 있습니까?C# 대리자가 스레드로부터 안전합니까?
대리자를 잠글 필요가 있습니까? 아니면 각 스레드가 자체 호출 스택을 가져 오기 때문에 각 스레드가 대리자가 가리키는 메서드를 호출하는 것이 안전합니까?
아니요 스레드로부터 안전하지 않으며 그렇습니다. 동시성을 직접 관리해야합니다. 직접 MulticastDelegate의 문서에서
는 :
이러한 유형의 멤버 (Visual Basic의 경우 Shared) 모든 공용 static 스레드로부터 안전합니다. 모든 인스턴스 멤버가 스레드로부터 안전하다는 보장은 없습니다.
Delegate 클래스에는 동일한 정보가 들어 있으므로 사용자가 가지고 있습니다.
이벤트 수정은 스레드로부터 안전하지는 않지만 대리인을 호출하는 것은 중요합니다. 대리자는 변경할 수 없으므로 스레드로부터 안전합니다.
이 here에서 빌린 : CLR 통해 C# 리히터에서 멀티 스레드 클래스에서 이벤트 호출에 대해 몇 가지 미묘한 점을 지적한다 : 여기 MSDN Delegate class 발언 참조
대리자 체인은 불변이다; 새로운 체인이 만들어져 첫 번째 체인을 대체합니다. 구독자가없는 대리인 체인이 null입니다. 즉, (귀하의 이벤트가 공개 된 경우) 언제든지 null에서 null이 아닌 그 반대가 될 수 있습니다.
"모든 인스턴스 멤버가 스레드 안전성을 보장하지 않습니다." - 귀하의 링크 – heisenberg
위임자의 호출과 관련하여 대답은 '예'입니다.
대리자 호출은 대리자가 불변이므로 스레드로부터 안전합니다. 그러나 먼저 대리자가 있는지 확인해야합니다. 이 검사에는 원하는 안전 수준에 따라 일부 동기화 메커니즘이 필요할 수 있습니다.
예를 들어, SomeDelegate
이 null 체크와 호출 사이의 다른 스레드에 의해 null로 설정된 경우, 다음은 NullReferenceException
을 던질 수 있습니다.
if (SomeDelegate != null)
{
SomeDelegate();
}
다음은 좀 더 안전합니다. 여기서 우리는 델리게이트가 불변이라는 사실을 이용합니다. 다른 스레드가 수정하더라도 SomeDelegate
코드는 성가신 것을 막기가 어렵습니다 NullReferenceException
.
Action local = SomeDelegate;
if (local != null)
{
local();
}
그러나,이 SomeDelegate
다른 스레드에서 null이 아닌 값이 할당 된 경우 대리자가 실행되고 있지 결코 될 수 있습니다. 이것은 미묘한 메모리 장벽 문제와 관련이 있습니다. 다음은 가장 안전한 방법입니다. 대답이 아니오 대리자가 참조하는 방법의 실행에 대해서
Action local = Interlocked.CompareExchange(ref SomeDelegate, null, null);
if (local != null)
{
local();
}
.
동기화 메커니즘을 사용하여 스레드 안전 보장을 제공해야합니다.이는 CLR이 대리자 실행을 위해 스레드 안전 보장을 자동으로 제공하지 않기 때문입니다. 특히 공유 상태에 액세스하지 않는 경우 안전을 위해 동기화를 더 이상 요구하지 않을 수도 있습니다. 그러나 메소드가 공유 변수를 읽거나 쓰는 경우 다중 스레드에서 동시에 액세스하지 못하게하는 방}을 고려해야합니다.
또는 간단하게 그것을'public 이벤트 SomeHandler MyEvent = {}'로 선언 할 수 있고 null이 아니게 보장됩니다. –
@Ed : 이벤트에 대해서는 작동하지만'SomeDelegate = null'을 수행 할 수 있으므로 원시 대리자에게는 작동하지 않습니다. –
네, 맞습니다. (잘못) 이벤트를 맡았습니다. –
대리인에 대해 변경 될 수있는 내용은 무엇입니까? (귀하의 의견은 이벤트에 대해서는 올바르지 만 대리인에 대한 변경 사항은 알 수 없습니다.) –
@ agent-j : 그것은 중요하지 않습니다. 기본 구현은 변경 될 수 있지만 현재 문서는 명시된 바와 같습니다. –