2008-09-18 5 views
14

WCF 서비스를 사용하는 Silverlight 2 응용 프로그램이 있습니다. 따라서 서비스 메소드에 대한 모든 호출에 대해 비동기 콜백을 사용합니다. 이러한 호출 전이나 도중에 서비스가 실행 중이 아니거나 서비스가 중단되거나 네트워크가 중단되는 경우 예상대로 예외가 생성됩니다. 문제는이 예외를 잡는 방법을 모른다는 것입니다. 이 비동기 호출이기 때문에Silverlight에서 WCF 예외를 잡는 가장 좋은 방법은 무엇입니까?

  • , 나는이 try/catch 블록으로 통화를 시작 포장하고 프로그램이 그 시점에서에 이동 한 후 발생하는 예외를 선택할 수 없습니다.

  • 서비스 프록시가 자동으로 생성되므로 EndInvoke (실제로 예외가 표시되는 곳)를 호출하는 모든 생성 된 함수에 try/catch 블록을 넣을 수 없습니다. 이러한 생성 된 함수는 호출 스택의 외부 코드에 의해 둘러싸이기 때문에 스택에 try/catch를 둘 수있는 아무 곳도 없습니다.

  • 예외가 호출되기 전에 try/catch를 콜백 함수에 넣을 수 없습니다.

  • 처리되지 않은 모든 예외를 캡처하는 App.xaml.cs에 Application_UnhandledException 함수가 있습니다. 나는 이것을 사용할 수는 있지만 그것을하는 것이 더러운 방법처럼 보인다. 차라리 예상치 못한 오류 (일명 버그)에 대해이 함수를 예약하고 특정 방식으로 처리하고 싶은 모든 상황에 대해이 함수에서 코드로 끝나지 않을 것입니다.

확실한 해결책이 없습니까? 아니면 Application_UnhandledException을 사용하여 붙어 있습니까?

[편집]
아래에서 언급했듯이 Error 속성은 내가 찾고있는 것입니다. 루프를 위해 나를 던지고있는 것은 예외가 던져져서 잡히지 않는 것처럼 보이지만 실행을 계속할 수 있다는 것입니다. Application_UnhandledException 이벤트를 트리거하고 VS2008이 실행을 중단 시키지만 디버거에서 계속하면 실행을 계속할 수 있습니다. 그것은 정말로 문제가 아니며 단지 이상하게 보입니다.

답변

12

서비스 메서드 완료 이벤트 처리기에서 이벤트 args의 Error 속성을 확인합니다. 이벤트 처리기가 호출되지 않는 문제는 없었습니다. 서버가 다운 된 경우에는 호출이 몇 초가 걸리고 Error 속성에 ProtocolException이 다시 발생합니다.

당신이 이것을 시도했지만 콜백이 실제로 호출되지 않는다고 가정하면 생성 된 프록시 클래스를 사용자 정의 할 수 있습니다. this article을 참조하십시오.

+0

"서비스 메소드 콜백"은 메소드 완료 이벤트를 의미하며 콜백이 아닙니다. 콜백은 APM과 함께 사용되지만 실버 라이트는 EAP를 사용합니다. –

+0

동의. 그에 따라 업데이트되었습니다. – dcstraw

5

나는 이것에 대해 이야기 한 a forum thread을 발견했으며, 가장 좋은 방법은 Error 속성을 사용하는 것이라고 언급했습니다. 이 스레드 내 자신의 경험 사이, 이것은 내가 결론을 내릴 수있는 것입니다 :

일반 .NET 코드에서
  • 는, 생성 된 프록시 클래스는 오류 속성에 예외를 두는 대신에 그것을 던져서 제대로 예외를 처리합니다.

  • Silverlight에서 생성 된 프록시 클래스는 Error 속성을 설정하지만 예외를 완전히 처리하지는 않습니다. 예외는 "ProtocolException was unusled by user code"라는 메시지와 함께 예외 상자를 팝업하는 디버거에 의해 선택됩니다. 이 메시지에도 불구하고, 예외는 실제로 Application_UnhandledException 함수를 만드는 것처럼 보이지 않습니다.

나는 이것이 최종 릴리스에서 해결할 것 중 하나라고 기대합니다.

지금은 Error 속성을 사용하고 디버거 실행을 중단합니다. 너무 성가 시게되면 ProtocolException 예외의 예외를 해제 할 수 있습니다.

0

당신은 asyn 클라이언트 콜백에 대한 Application_UnhandledException을 잊을 수는, 왜 이유 :

Application_UnhandledException 유일한 예외는 UI 스레드에서 해고 이것은 의미 Application.UnhandledExceptions

에 걸려 수 있습니다 ...에서 호출되지 모든 WCF 비동기 호출에 대한 :-).

http://silverlight.net/forums/t/21828.aspx

안녕하세요 MSFT에서

확인 상세한 응답, UI 스레드에서 해고 유일한 예외는 Application.UnhandledExceptions에 의해 체포 될 수있다. 다른 스레드에서 예외를 catch 할 수 없습니다. 이 문제를 해결하기 위해이 문제를 해결할 수 있습니다. Visual Studio의 디버그 메뉴에서 예외를 선택합니다. 그런 다음 "공용 언어 런타임 예외"를 선택하십시오. 이렇게하면 예외가 발생할 때마다 디버거가 중지됩니다. 그러나 예외가 이미 잡히는 경우에도 이후로는 때로는 매우 성가 시게됩니다. CheckBox를 사용하여 catch하려는 예외를 필터링 할 수 있습니다.

필자의 경우 좋은 소식은 디버깅을하지 않으면 clietn 서비스 콜백에서 오류 메시지 만 처리하면 충분하다는 것입니다.

감사

Braulio 
+3

그렇지 않습니다. 예외가 WCF 서비스에서 시작된 경우 Application_UnhandledExceptions를 가장 많이 쳤습니다. 나는 던져진 FaultException을 쉽게 확인할 수 있기 때문에 알 수 있습니다. – Rire1979

0

OOpps .... 내 옆에서

죄송 오답 (물론 MSFT 사람이 콜백은 동일한 UI 스레드에서 호출되는 쓰기 응답 서비스를 명중하지 않았다)

- In development even detaching from the debugger, this method is never reached. 
- On the production environment yes. 

내 생각 엔 뭔가 VISU 관련 : 문제는

자세한 정보입니다 모든 Studio 옵션 및 차단 예외.

더 많은 정보를 원하시면,이 스레드 http://silverlight.net/forums/p/48613/186745.aspx#186745

아주 흥미로운 주제이다.

0

나는 배관공이 아니므로 Visual Studio에서 자동 생성 한 클래스 파일 "reference.cs"의 기능 중 일부를 재정의하는 자체 WCF 서비스 클래스를 만들기로 결정하고 직접 테스트를 추가했습니다./통신 오류를 잡을 수있는 블록 잡기. 혼동 - - 도달하지 않습니다 Visual Studio 디버거 예외 핸들러 있도록 이러한 예외를 잡는다 실버 3으로

public class myWCFService : MyWCFServiceClient 
{ 

    protected override MyController.MyService.IMyWCFService CreateChannel() 
    { 
     return new MyWCFServiceClientChannel(this); 
    } 

} 

private class MyWCFServiceClientChannel : ChannelBase<MyController.MyService.IMyWCFService>, MyController.MyService.IMyWCFService 
{ 
    /// <summary> 
    /// Channel Constructor 
    /// </summary> 
    /// <param name="client"></param> 
    public MyWCFServiceClientChannel(System.ServiceModel.ClientBase<MyController.MyService.IMyWCFService> client) : 
    base(client) 
    { 
    } 
    /// <summary> 
    /// Begin Call To RegisterUser 
    /// </summary> 
    /// <param name="memberInformation"></param> 
    /// <param name="callback"></param> 
    /// <param name="asyncState"></param> 
    /// <returns></returns> 
    public System.IAsyncResult BeginRegisterUser(MyDataEntities.MembershipInformation memberInformation, System.AsyncCallback callback, object asyncState) 
    {    
     object[] _args = new object[1]; 
     _args[0] = memberInformation; 
     System.IAsyncResult _result = base.BeginInvoke("RegisterUser", _args, callback, asyncState); 
     return _result;    
    } 
    /// <summary> 
    /// Result from RegisterUser 
    /// </summary> 
    /// <param name="result"></param> 
    /// <returns></returns> 
    public MyDataEntities.MembershipInformation EndRegisterUser(System.IAsyncResult result) 
    { 
     try 
     { 
      object[] _args = new object[0]; 
      MyDataEntities.MembershipInformation _result = ((MyDataEntities.MembershipInformation)(base.EndInvoke("RegisterUser", _args, result))); 
      return _result; 
     } 
     catch (Exception ex) 
     { 
      MyDataEntities.MembershipInformation _result = new MyDataEntities.MembershipInformation(); 
      _result.ValidationInformation.HasErrors = true; 
      _result.ValidationInformation.Message = ex.Message; 
      return _result; 
     } 
    } 
} 
+1

Message 속성 이외의 예외 부분을 모두 버리는 이유는 무엇입니까? 정보를 버리는 것은 결코 좋은 생각이 아닙니다. –

+0

요한이 한 말. StackTrace와 InnerException은 특히 유용합니다. – MetalMikester

0

:

내가 만든 클래스는 다음과 같이 보인다.그러나 디버거없이 실행하면 예외 처리기가 예상대로 호출됩니다. 나는 이것이 그 사실을 알고있는 한 이것이 괜찮다고 생각한다. 나는 몇 시간 동안 Silverlight/Wcf/Browser의 내부 작업을 드릴 다운하여 예외 처리하는 방법을 알아 내려고 노력했다. 거기 가지마.

0

Silverlight에서 비동기 예외를 처리하는 데는 사용자 지정 WCF 프록시 생성기를 사용하는 것이 좋습니다. here 소스 코드를 다운로드하려면 클릭하십시오.

0

WPNA에서 XNA를 사용하면 다양한 비동기 End * FunctionName *() 메서드에 try/catch를 수동으로 추가 할 수 밖에 없었습니다. 내가 시도한 다른 것은 서버를 사용할 수 없을 때 응용 프로그램 오류 & 종료를 막을 수 있습니다. 서비스가 변경되면이 코드를 수동으로 업데이트해야하는 실제적인 문제입니다.

XNA를 사용하여 WP7에서 이러한 예외를 catch하는 다른 방법이없는 것 같기 때문에 이것이 더 큰 문제는 아니지만 놀랍습니다. 그러나이 방법이 얼마나 많은 (== 많지는 않은) 사람들에 대해 더 많이 말하고 있다고 가정합니다 다른 일보다이 일을하려고합니다. slsvcutil.exe가 동기화 메서드를 생성하게되면 우리 고유의 작업자 스레드 내에서 이들을 쉽게 catch 할 수 있지만 불행히도 생성 된 코드는 스레드 풀 스레드를 사용하여 예외를 catch 할 수 없습니다.

0

이 상황을 처리하려면 TargetInvocationException을 사용하십시오. 이렇게하면 네트워크가 다운되었거나 서비스를 사용할 수 없을 때 예외가 발생합니다.