개요: 이 섹션에서는 서비스 호출에서 발생할 수 있는 예외 및 시뮬레이션된 예외를 주로 설명하고, 언제, 어떤 예외가 catch될 수 있는지 분석하고 서비스 예외를 올바른 방식으로 클라이언트에 전달하는 방법을 설명합니다.
기사 마지막에는 예외를 올바르게 포착하기 위한 포착 순서가 제공됩니다. 이 예외 캡처는 단지 소개일 뿐이고 그 중 일부는 애플리케이션 기능이므로 코드와 작성이 비교적 간단합니다. 또한 서버 측에서 예외 처리를 위한 몇 가지 기술도 소개합니다.
1. 먼저 다음과 같이 간단한 계산기 서버와 클라이언트를 만듭니다.
코드를 확장하려면 클릭하세요.
//서버[ServiceContract]공용 인터페이스 ICalc{[OperationContract][FaultContract(typeof(GreentingError))]string Div(int x, int y);}공용 클래스 Calc : ServiceBase, ICalc {공용 문자열 Div(int x, int y ) ) {string result = string.Empty; try {result = string.Format("result: {0}", x / y) } catch (DivideByZeroException ex) {throw ex; [ServiceContract] 공용 인터페이스 ICalc { [OperationContract] [FaultContract(typeof(GreentingError))] string Div(int x, int y) } public class CalcClient : ClientBase<ICalc>, ICalc{ public string Div(int x, int y ) ) {return base.Channel.Div(x, y) }}
좋아요, 코드가 매우 간단하다는 것은 인정하지만 저는 단순한 것을 좋아합니다.
2. 단순한 것이 좋고, 호출하는 것이 훨씬 간단합니다.
try { CalcClientcalcclient = new CalcClient(); string result =calcclient.Div(10, 0); Console.WriteLine(result); Console.ReadKey() } catch (TimeoutExceptionex) {throw ex; ex) {throw ex; } catch(FaultExceptionex) {throw ex; catch(System.ServiceModel.CommunicationException ex) {throw ex } catch(Exceptionex) {throw ex;
3. 서비스의 Div(int x, int y) 메서드를 호출하고 값 0을 로그 y에 전달하면 서버는 예상한 DivideByZeroException 예외를 발생시킵니다. 이때,
이 예외는 클라이언트의 FaultException 섹션에서 발견됩니다.
4. 문제 없습니다. 서버 코드에서 FaultException을 수동으로 발생시킵니다.
catch (DivideByZeroException ex){FaultException 예외 = new FaultException(ex.Message) 예외 발생;}
이때 FaultException이 이 예외를 포착한 것을 발견했습니다. 이유는 무엇입니까?
5. 또 다른 테스트를 수행합니다.
서비스에 System.Threading.Thread.Sleep(70000) 코드를 추가하면 서비스 시간이 초과됩니다.
이번에는 TimeOutException이 마침내 서버 예외를 포착했기 때문에 FaultException<GreentingError>가 언제 예외를 포착할 것인지 물어봐야 합니다. 대답은 서버에서 FaultException<GreentingError>가 발생하면 MSDN(녹색 부분)에서 다음 구절을 인용하는 것입니다.
수신기가 예상되지 않거나 작업 계약에 지정되지 않은 SOAP 오류를 수신하는 경우 FaultException 개체가 발생합니다. 두 가지 유형의 SOAP 오류(선언 및 선언 취소)가 전송될 수 있습니다. 선언된 SOAP 오류는 작업에 사용자 지정 SOAP 오류 유형을 지정하는 System.ServiceModel.FaultContractAttribute 특성이 있는 오류입니다. 선언되지 않은 SOAP 오류는 작업 계약에 지정되지 않은 오류입니다. 여기서 "예기치 않은 또는 지정되지 않은 SOAP 오류"는 서비스 작업에서 FaultContractAttribute로 래핑되지 않은 사용자 지정 오류 유형을 나타냅니다.
6. 그러면 CommincationException은 언제 발생하나요?
MSDN에 따르면 응용 프로그램은 통신 중에 발생할 수 있는 CommunicationException 개체를 처리합니다.
이 예외를 발생시키기 위해 다음을 수행합니다. 먼저 서버에서 현재 채널 개체를 닫습니다.
OperationContext.Current.Channel.Close();
불행하게도 클라이언트는 CommunicationException을 포착하지 못했지만 TimeOutException을 포착했습니다! 서비스 채널이 닫힌 후 예외가 발생하지 않았기 때문에 일정 시간 동안 기다린 후에도 클라이언트가 시간 초과되어 종료되었습니다.
따라서 채널을 닫는 동안 TimeSpan을 지정합니다. 이를 통해 호출이 즉시 반환될 수 있습니다. 물론 호출 반환은 Channel.Abort를 통해 완료될 수도 있습니다.
OperationContext.Current.Channel.Close(new TimeSpan(5000));
IContextChannel의 Close 메서드를 호출할 때 시간 초과 전에 전송 작업이 완료되어야 하는 시간을 지정하면 서비스 호출이 시간 초과될 때까지 기다릴 필요 없이 지정된 시간 내에 메시지가 즉시 반환될 수 있습니다. 그렇지 않으면 클라이언트에서 분명히 오류가 발생합니다. CommunicationException 예외 대신 TimeOutException 예외.
7. 구제책
동시에 서비스에서 예외가 발생할 때 몇 가지 수정 조치를 취하기 위해 새로운 추상 클래스 ServiceBase를 생성하고 Calc 서비스 구현 클래스를 이 클래스에서 상속하도록 하여 다양한 상태 전환을 제어할 수 있습니다. 서비스. ServiceBase 클래스는 다음과 같습니다.
공용 추상 부분 클래스 ServiceBase { 개인 IContextChannel 채널 = null; 보호된 ServiceBase() { 채널 = OperationContext.Current.Channel; 채널.Opening += new EventHandler(delegate(object sender, EventArgs e) {/* 수행할 작업*/ }) ; 채널.열림 += new EventHandler(delegate(객체 전송자, EventArgs e) {/* 수행할 작업*/ }); 채널.Closing += new EventHandler(delegate(객체 전송자, EventArgs e) {/* 수행할 작업*/ }); 채널.Closed += new EventHandler(delegate(object sender, EventArgs e) { Abort(); }); ; } void Open() {/* 수행할 작업*/ } void Close() { /* 수행할 작업*/} void Abort() { 채널.Abort() }}
위의 코드에서 알 수 있듯이 서비스 채널이 닫힌 후에는 즉시 서비스를 중지하고 메시지가 즉시 반환되도록 합니다. 이때 타임아웃 완료 시간을 지정하지 않고 작업 중에 서비스가 닫히더라도 호출이 발생합니다. 여전히 즉시 돌아올 수 있습니다.
이번에는 클라이언트가 마침내 아래 그림과 같이 CommunicationException을 포착했습니다.
왜 이런 일이 발생합니까?
8. 영감을 얻을 수 있는 CommunicationException의 상속 계층 구조를 살펴보겠습니다.
8.1. 첫 번째는 FaultException<TDetail>의 상속 계층입니다.
8.2, 다시 TimeOutException의 상속 계층 구조입니다.
9. 위 그림에서 볼 수 있듯이 TimeOutException과 CommunicationException은 모두 SystemException 클래스를 상속하고, FaultException은 CommunicationException을 상속하고, 마지막으로 FaultException<TDetail>은 FaultException 클래스를 상속합니다.
10. 마지막으로 클라이언트에서 예외를 포착하는 올바른 순서는 다음과 같아야 한다고 결론을 내렸습니다.
TimeOutException> FaultException<TDetail> > FaultException > CommunicationException > 예외. 개발자는 FaultException<TDetail> 유형의 예외를 발생시키고 포착하는 것이 좋습니다.
저자: Lao Mi 출처: http://www.cnblogs.com/viter/
이 글의 저작권은 글쓴이에게 있으며, 재인쇄는 환영합니다. 단, 이 글은 글쓴이의 동의 없이 그대로 유지되어야 하며, 그렇지 않은 경우 원문에 대한 링크를 글 페이지의 눈에 띄는 위치에 제공해야 합니다. 법적 책임을 추구할 권리가 있습니다.