2012-05-11 12 views
0

Begin/Endメソッドを使用して非同期メソッドを使用してWPFアプリケーションでサービスをホストしていて、私はfaultExceptionをスローしてクライアントに警告したいと思います。障害例外(非同期メソッド)をスローすると、WPF自己ホストアプリケーションのWCFサービスがクラッシュする

しかし、faultExceptionをスローしようとすると、ホストアプリケーションがクラッシュし、突然シャットダウンします。

私のリポジトリで、私はUpdateExceptionをキャッチし、UniqueKeyExceptionというカスタム例外を作成して呼び出し側にスローします。呼び出し元は、Beginメソッドで呼び出される、慣れ親しんだメソッドです。

この便利な方法は、UniqyeKeyExceptionをキャッチして、 "終了"のtry/catchブロックでキャプチャされる "throw"のみを実行します。ここには私が理解していない何かがあります。なぜなら、この例外はUniqueKeyExceptionの代わりにAgregateExceptionのブロック内にキャッチされるからです。

とにかく、endメソッドのcatchブロックのAgregateExceptionブロックで、innerExceptionがUniqueKeyExceptionであるかどうかをチェックし、trueの場合、オブジェクトUniqueKeyArgs(送信する情報を持つカスタムクラス)を作成しますFaultExceptionを作成し、最後にFaultExceptionをスローします)。このステップでは、ホストアプリケーションがクラッシュするスローが発生します。

私のカスタムクラスUniqueKeyArgsはDatacontractとDataMemberとしてのプロパティとして、私のホストアプリケーションのapp.configで飾り付けされているので、私はすべて正しく構成していると思います。例外の詳細と契約Iを含むように振る舞いを構成します。それをfaultContractで飾ります。

なぜアプリケーションがクラッシュするのですか?

私のコードは以下の通りです:

リポジトリ

public List<Usuers> updateUsers(List<Users> paramUsers) 
{ 
.... 

catch(UpdateException ex) 
{ 
SqlException innerEx = (SqlException)ex.InnerException; 

       //Code 2627 is Unique Key exception from SQL Server. 
       if (innerEx != null && innerEx.Number == 2627) 
       { 
        //I create the conditions of searching 
        ConditionsUsers conditions = new conditions(); 

        conditions.UserName = (Users)ex.StateEntries[0].Entity).userName; 

        //Search for the existing user 
        Users myUser = getUser(conditions); 
        string message = "the user " + conditions.userName + " exists."; 
        throw new UniqueKeyException(message, myUser); 
       } 
       throw; 
} 

サービスの実装

//This is my auxiliar method, called in the Begin method. 
private submitUpdates() 
{ 
    .... 

    catch(UniqueKeyException ex) 
    { 
      //The code enter here 
      throw; 
    } 
} 



public IAsyncResult BeginUpdateUsers(List<users> paramUsers, AsyncCallback callback, object state) 
{ 
    Task<List<Users>> myTask= Task<List<Users>>.Factory.StartNew(p => sumbmitUpdates(paramUsers), state); 
    return myTask.ContinueWith(res => callback(myTask)); 
} 


public List<Users> EndUpdateusers(IAsyncResult result) 
    { 
      try 
      { 
       return ((Task<List<Users>>)result).Result; 
      } 
      //Why agregateException and not is catched in the UniqueKeyException ??? 
      catch(AgregateException ex) 
      { 
       if (innerExceptions[0] is UsuariosValorUnicoException) 
        { 
         //I assign manually the data to debug, to discard other problems. 
         Users myUser = new Users(); 
         myUser.UserName = "Jhon"; 
         myUser.Password = "pass123"; 
         UniqueKeyArgs myArgs = new UniqueUserArgs("unique key error", myUser); 
         FaultException<UniqueKeyArgs> myException = new FaultException<UniqueKeyArgs>(myArgs); 

         //Crash here, in the throw myException 
         throw myException;       
        } 
       } 
       throw; 
      } 

MY契約

[FaultContract(typeof(UniqueKeyArgs))] 
IAsyncResult BeginUpdateUsers(List<Users> paramUser, AsyncCallback callback, object state); 
List<Users> EndUpdateUsers(IAsyncResult result); 

クラッシュ私が最後にmyExceptionを投げます方法。

このpostでは、サービスオブジェクト内だけでなく、ホストアプリケーションでも例外がキャッチされることがわかりました。ただし、このソリューションは、System.Windows.Forms名前空間に属するApplication.ThreadExceptionを使用し、WPFアプリケーションを使用しています。

WPFアプリケーションでホストされているサービスからクライアントに例外を送信するにはどうすればよいですか?

ありがとうございました。

EDIT1:

:まあ、私は例外をスローし、私はエラーが私は私のFaultExceptionを作成するときに私は、私はその理由を示していないことであることがわかり行にtry/catchブロックを使用しています
FaultException<UniqueKeyArgs> myException = new FaultException<UniqueKeyArgs>(myArgs, new FaultReason("DummyReason"); 

この場合、例外メッセージはFaultReasonで設定したメッセージである「DummyReason」で、何も表示されません。 FaultExceptionはthrowではなく、汎用例外をクライアントにスローします。

この場合、ホストアプリケーションはシャットダウンしませんが、クライアントとの接続を閉じて再接続する必要があります。

問題はFaultExceptionの原因になっているようですが、問題は見えません。

@Roealは、おそらく同期メソッドでfaultExceptionを使用することしかできないと示唆していますが、このlinkでは非同期メソッドで使用される例が分かります。私は他の例を見てきました、ユニークではありません。

ありがとうございました。

EDIT2:私の問題を解決します。私の問題は、FaultExceptionでは、Tは自己追跡エンティティであったプロパティを持つオブジェクトで、これは問題です。間違っていない場合は、例外のプロパティとして基本型しか使用できません。

次に、例外として、私はISerializeを含意しました。クライアントに情報を送信できるようにする必要がありますが、クライアントはヌルプロパティを持つexception.Detailを受け取ります。

+0

解決策を質問に編集したり、タイトルに「解決済み」を入れないでください。解答として投稿してください。その後、問題が解決されたことを示す(遅れて)それを受け入れることができます。 – ChrisF

答えて

0

私は私の問題を解決します。私の問題は、FaultExceptionでは、Tは自己追跡エンティティであったプロパティを持つオブジェクトで、これは問題です。間違っていない場合は、例外のプロパティとして基本型しか使用できません。

次に、例外として、私はISerializeを含意しました。クライアントに情報を送信できるようにする必要がありますが、クライアントはヌルプロパティを持つexception.Detailを受け取ります。

1

サービス契約で同期操作も宣言しましたか?その場合には、多分これは役立ちます:フォールト契約はサービス運用契約に定義されている場合

は、FaultContract属性は同期操作にを適用する必要があります。
- ジュバル・ロウィ、 "プログラミングWCFサービスの第3版"(P456)

+0

ありがとう、一部のサイトでは、非同期メソッドでfaultExceptionを使用することが可能です。私は自分の投稿の中の1つのリンクをedit1に追加します。ありがとう。 –

+0

私は彼があなたのサービス契約で定義されている**両方の**操作を持っていると思うので(同期と非同期の両方)、属性は同期操作の* only *でなければなりません – RoelF

+0

私の場合、メソッドの同期バージョン、私は非同期しか持っていません。 –