2014-12-29 1 views
2

나는 공급자/소비자 패턴을 구현하는 C#을 서버가 있습니다. 이 서버에는 일부 데이터를 생성하는 공급자 스레드가 있습니다. 여러 소비자 스레드가 데이터를 소비합니다. 데이터에 대한 액세스가 제대로 잠겨 모든 것이 올바르게 작동합니다. 그러나 때로는 공급자 스레드가 데이터를 가져올 수 없습니다. 이 경우에는 예외가 발생합니다. 예외가 동일한 스레드 내에서 발견되었습니다. 그러나 예외가 발생한 후에는 모든 소비자 스레드에서이 동일한 예외를 throw해야합니다. 그래서 질문이 : 하나의 예외 개체를 여러 스레드에 여러 번 던질 안전합니까? CLR Exception과 Exception을 상속받은 모든 클래스에는 [Serializable] 특성이 있어야 함을 알고 있습니다. 이것은 Exception 객체가 던지기에 직렬화된다는 표시 일 수도 있지만 이것에 대한 정보를 찾을 수 없습니다.하나의 C# 예외가 여러 스레드에서 여러 번 throw 될 수 있습니까?

+2

예외는 AppDomain 경계를 넘을 수 있기 때문에 직렬화 가능해야합니다. 스레드에 아무런 영향을주지 않습니다. 그러나 예외를 다시 던지면 스택 추적을 날려 버릴 것입니다. 새로운 예외로 랩핑하고 통지해야하는 각 스레드를 던지는 것이 좋습니다. –

+0

문제는 흥미로울 것 같지만 정확히 무엇을 요구하는지 확신 할 수 없습니다. – leppie

답변

2

는 여러 스레드에서 하나의 예외 객체를 여러 번 던져 것이 안전하다?

예, 예외 객체가 스레드 안전 인 것으로 가정하면 안전합니다. Exception 다중 스레드에서 다시 throw하는 개체가 스레드로부터 안전하다는 것을 확인하면 동일한 개체를 여러 곳에서 다시 사용할 때 아무런 문제가 없습니다 *.

그러나 각 소비자 스레드가 원래 예외에 대한 응답으로 자체 예외를 throw하고 원래 예외를 생성자의 innerException 매개 변수로 사용하는 것이 좋습니다. 내부 예외는 모든 스레드에서 공유 유지,하지만 중첩 된 구조는 더 나은 예외를 catch 사용자의 관점에서 무슨 일이 있었는지 반영.

원래 예외를 다시 throw하는 경우이를 catch하는 사용자는 생산자 스레드 인 원래 보낸 사람 만 찾을 수 있습니다. 그들이 소비자 스레드에서 예외가 발생하기 때문에, 혼동 될 수 있습니다, 그래서 그들은 스택 추적이 해제 될 것이기 때문에, 힘든 시간을 제외 이어질 일련의 사건을 조립할있을 것입니다.

반면에 중첩 예외는 소비자 스레드에서 발생하지만 innerException을 근본 원인으로 제공하므로 캐처가 정확히 무슨 일이 발생했는지 더 잘 알 수 있습니다.

CLR Exception 및 Exception을 상속하는 모든 클래스에는 [Serializable] 특성이 있어야한다는 것을 알고 있습니다. 이것은 Exception 객체가 던지기에 직렬화된다는 표시 일 수도 있지만 이것에 대한 정보를 찾을 수 없습니다.

[Serializable] 속성을 추가하는 이유는 this Q&A에 설명되어 있습니다. 동일한 앱 도메인 내의 여러 스레드에 대한 예외 사용 가능성에는 아무런 영향을 미치지 않습니다.

* 다시 스레드가 다른 스레드에서 같은 메서드의 같은 지점에서 발생한다고 가정합니다.

+0

당신은 옳을 수도 있지만, 소비자들은 적절한 유형의 예외를 기다리고 있습니다. 나는 serialize/deserializing 및 복사 던져 예외를 복사하는 것이 좋습니다. – Slava

+0

@Slava 원래 스택 추적을 유지할 수는 없지만 작동 할 수도 있습니다. 동일한 타입과 모든 것을 가지고 똑같은 예외의 아주 새로운 인스턴스를 만들 수 있지만 원래의 예외를 두 개의 스택 트레이스를 따로 보존하기위한'innerException'으로두면된다. – dasblinkenlight

+0

공급 업체가 생산 한 예외 유형을 정확히 알지 못합니다. 리플렉션을 사용하여 형식 이름을 얻고 같은 예외를 생성 할 수 있다는 것을 알고 있지만 코드 유지 관리가 복잡해집니다. 그리고 실제로 공급자 스택이 필요하지 않습니다. 맞춤 예외 유형에는 모든 정보 소비자가 필요합니다. – Slava

1

예외 직렬화 할 수 있지만 필요가 없습니다. 예를 들어 원격를 사용하여 응용 프로그램 도메인을 통과해야하는 경우 직렬화하지만 시나리오의 경우 될 것 같지 않습니다.

예외적으로 일반적인 스레딩 및 동기화 문제가 적용됩니다. 예외는 생성자에서 읽기 전용 상태 만 설정하면 (기본적으로 스레드 세이프) 본질적으로 스레드 안전합니다.

한 가지 더 : 다시 예외를 던질 때마다 예외 인스턴스의 스택 추적을 덮어 씁니다. 그것이 던지는 마지막 위치가 이기게됩니다. 따라서 다른 예외 (예 : TargetInvocationException)에 예외를 래핑하는 것이 좋습니다.

관련 문제