나는 공급자/소비자 패턴을 구현하는 C#을 서버가 있습니다. 이 서버에는 일부 데이터를 생성하는 공급자 스레드가 있습니다. 여러 소비자 스레드가 데이터를 소비합니다. 데이터에 대한 액세스가 제대로 잠겨 모든 것이 올바르게 작동합니다. 그러나 때로는 공급자 스레드가 데이터를 가져올 수 없습니다. 이 경우에는 예외가 발생합니다. 예외가 동일한 스레드 내에서 발견되었습니다. 그러나 예외가 발생한 후에는 모든 소비자 스레드에서이 동일한 예외를 throw해야합니다. 그래서 질문이 : 하나의 예외 개체를 여러 스레드에 여러 번 던질 안전합니까? CLR Exception과 Exception을 상속받은 모든 클래스에는 [Serializable]
특성이 있어야 함을 알고 있습니다. 이것은 Exception 객체가 던지기에 직렬화된다는 표시 일 수도 있지만 이것에 대한 정보를 찾을 수 없습니다.하나의 C# 예외가 여러 스레드에서 여러 번 throw 될 수 있습니까?
답변
는 여러 스레드에서 하나의 예외 객체를 여러 번 던져 것이 안전하다?
예, 예외 객체가 스레드 안전 인 것으로 가정하면 안전합니다. Exception
다중 스레드에서 다시 throw하는 개체가 스레드로부터 안전하다는 것을 확인하면 동일한 개체를 여러 곳에서 다시 사용할 때 아무런 문제가 없습니다 *.
그러나 각 소비자 스레드가 원래 예외에 대한 응답으로 자체 예외를 throw하고 원래 예외를 생성자의 innerException
매개 변수로 사용하는 것이 좋습니다. 내부 예외는 모든 스레드에서 공유 유지,하지만 중첩 된 구조는 더 나은 예외를 catch 사용자의 관점에서 무슨 일이 있었는지 반영.
원래 예외를 다시 throw하는 경우이를 catch하는 사용자는 생산자 스레드 인 원래 보낸 사람 만 찾을 수 있습니다. 그들이 소비자 스레드에서 예외가 발생하기 때문에, 혼동 될 수 있습니다, 그래서 그들은 스택 추적이 해제 될 것이기 때문에, 힘든 시간을 제외 이어질 일련의 사건을 조립할있을 것입니다.
반면에 중첩 예외는 소비자 스레드에서 발생하지만 innerException
을 근본 원인으로 제공하므로 캐처가 정확히 무슨 일이 발생했는지 더 잘 알 수 있습니다.
CLR Exception 및 Exception을 상속하는 모든 클래스에는
[Serializable]
특성이 있어야한다는 것을 알고 있습니다. 이것은 Exception 객체가 던지기에 직렬화된다는 표시 일 수도 있지만 이것에 대한 정보를 찾을 수 없습니다.
[Serializable]
속성을 추가하는 이유는 this Q&A에 설명되어 있습니다. 동일한 앱 도메인 내의 여러 스레드에 대한 예외 사용 가능성에는 아무런 영향을 미치지 않습니다.
* 다시 스레드가 다른 스레드에서 같은 메서드의 같은 지점에서 발생한다고 가정합니다.
당신은 옳을 수도 있지만, 소비자들은 적절한 유형의 예외를 기다리고 있습니다. 나는 serialize/deserializing 및 복사 던져 예외를 복사하는 것이 좋습니다. – Slava
@Slava 원래 스택 추적을 유지할 수는 없지만 작동 할 수도 있습니다. 동일한 타입과 모든 것을 가지고 똑같은 예외의 아주 새로운 인스턴스를 만들 수 있지만 원래의 예외를 두 개의 스택 트레이스를 따로 보존하기위한'innerException'으로두면된다. – dasblinkenlight
공급 업체가 생산 한 예외 유형을 정확히 알지 못합니다. 리플렉션을 사용하여 형식 이름을 얻고 같은 예외를 생성 할 수 있다는 것을 알고 있지만 코드 유지 관리가 복잡해집니다. 그리고 실제로 공급자 스택이 필요하지 않습니다. 맞춤 예외 유형에는 모든 정보 소비자가 필요합니다. – Slava
예외 는 직렬화 할 수 있지만 필요가 없습니다. 예를 들어 원격를 사용하여 응용 프로그램 도메인을 통과해야하는 경우 직렬화하지만 시나리오의 경우 될 것 같지 않습니다.
예외적으로 일반적인 스레딩 및 동기화 문제가 적용됩니다. 예외는 생성자에서 읽기 전용 상태 만 설정하면 (기본적으로 스레드 세이프) 본질적으로 스레드 안전합니다.
한 가지 더 : 다시 예외를 던질 때마다 예외 인스턴스의 스택 추적을 덮어 씁니다. 그것이 던지는 마지막 위치가 이기게됩니다. 따라서 다른 예외 (예 : TargetInvocationException)에 예외를 래핑하는 것이 좋습니다.
- 1. 예외가 throw 될 수 있습니다.
- 2. 하나의 요소 여러 번
- 3. 다른 스레드에서 예외가 throw 될 때 스택 추적을 작성하십시오.
- 4. 여러 번 던진 예외가 확인되었거나 런타임에 있습니까?
- 5. 다른 스레드에서 배열을 여러 번 확인할 수 있습니까?
- 6. 은 예외가 throw 될 때 코드를 실행할 수 있습니까?
- 7. 하나의 try 블록에서 여러 예외가 발생했습니다.
- 8. 한 번 Lua 스크립트를로드하고 여러 스레드에서 여러 상태로 실행
- 9. DynamicProxy 생성기를 여러 스레드에서 사용할 수 있습니까?
- 10. 스프링 통합시 여러 스레드에서 여러 스레드의 메시지를 하나의 채널로 보냅니다.
- 11. 하나의 쿼리에서 여러 번 계산
- 12. AsyncTask에서 HttpClient를 여러 번 실행할 수 있습니까?
- 13. 여러 스레드에서 여러 작업 예약
- 14. 하나의 SQL로 다른 where 절을 여러 번 사용할 수 있습니까?
- 15. 예외 처리 : 예외가 여러 번 처리되었습니다.
- 16. C# 예외가 throw/catch되지 않습니다.
- 17. 스레드를 여러 번 실행할 수 있습니까?
- 18. 하나의 스레드에서 여러 스레드로 작업을 분산하는 방법
- 19. 여러 스레드에서 동일한 CGContextRef를 그릴 수 있습니까?
- 20. 핫 샷을 여러 스레드에서 사용할 수 있습니까?
- 21. 하나의 문서 조각을 여러 번 사용할 수 있습니까?
- 22. 하나의 의도를 여러 번 발사 할 수 있습니까?
- 23. 하나의 라켓 프로그램에서 모듈을 여러 번 인스턴스화 할 수 있습니까?
- 24. 하나의 Instansiation으로 Rust 매크로에서 인수를 여러 번 사용할 수 있습니까?
- 25. 여러 iOS 개발자 프로그램 계정에서 하나의 기기가 될 수 있습니까?
- 26. 시스템에서 결정한대로 여러 스레드에서 하나의 메소드를 실행하십시오.
- 27. 안정적으로 여러 스레드에서 하나의 PrintWriter로 쓰기
- 28. 하나의 스레드에서 X509Certificate2 객체를 인스턴스화 한 다음 WCF 호출을 위해 여러 스레드에서 사용할 수 있습니까?
- 29. C# 스레드가 여러 번 시작하는 것 같습니다.
- 30. 하나의 Rails 앱을 여러 번 구현
예외는 AppDomain 경계를 넘을 수 있기 때문에 직렬화 가능해야합니다. 스레드에 아무런 영향을주지 않습니다. 그러나 예외를 다시 던지면 스택 추적을 날려 버릴 것입니다. 새로운 예외로 랩핑하고 통지해야하는 각 스레드를 던지는 것이 좋습니다. –
문제는 흥미로울 것 같지만 정확히 무엇을 요구하는지 확신 할 수 없습니다. – leppie