Begin/end メソッドを使用した非同期メソッドを使用して WPF アプリケーションでホストされているサービスがあり、サービスで例外をキャッチしたときに、クライアントに警告するために faultException をスローしたいと考えています。
しかし、faultException をスローしようとすると、ホスト アプリケーションがクラッシュし、突然シャットダウンします。
私のリポジトリでは、UpdateException をキャッチしてから、呼び出し元にスローされるカスタム例外 UniqueKeyException を作成します。呼び出し元は、Begin メソッドで呼び出される補助メソッドです。
この補助メソッドは、UniqyeKeyException をキャッチし、「スロー」のみを実行します。これは、終了メソッドの try/catch ブロックでキャプチャされます。ここで私が理解できないことがあります.なぜこの例外がUniqueKeyExceptionではなくAgregateExceptionのブロックでキャッチされるのか.
まぁ、とにかく end メソッドの catch ブロックで、AgregateException ブロックで、innerException が UniqueKeyException かどうかをチェックし、true ならオブジェクト UniqueKeyArgs (クライアントに送信する情報を持つカスタム クラス) を作成し、 FaultException を作成し、最後に FaultException をスローします。ホスト アプリケーションがクラッシュするのは、このスローの段階です。
私のカスタムクラスUniqueKeyArgsはDatacontractとして装飾され、そのプロパティはDataMemberとして装飾されているため、ホストアプリケーションのapp.configで例外の詳細を含めるように動作を構成し、コントラクトで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;
}
私の契約
[FaultContract(typeof(UniqueKeyArgs))]
IAsyncResult BeginUpdateUsers(List<Users> paramUser, AsyncCallback callback, object state);
List<Users> EndUpdateUsers(IAsyncResult result);
End メソッドで myException をスローするとクラッシュします。
この投稿では、サービス オブジェクトだけでなく、ホスト アプリケーションでも例外をキャッチすることが解決策であることがわかります。ただし、このソリューションでは System.Windows.Forms 名前空間に属する Application.ThreadException を使用しており、私は WPF アプリケーションを使用しています。
WPF アプリケーションでホストされているサービスからクライアントに例外を送信するにはどうすればよいですか?
ありがとう。
EDIT1:まあ、例外をスローする行でtry/catchブロックを使用していますが、エラーは理由を示していないことがわかります。したがって、FaultExceptionを作成するときに次のようにします。
FaultException<UniqueKeyArgs> myException = new FaultException<UniqueKeyArgs>(myArgs, new FaultReason("DummyReason");
この場合、例外メッセージは "DummyReason" で、FaultReason で設定したメッセージなので、何も表示されません。FaultException はスローされず、一般的な例外がクライアントにスローされます。
この場合、ホスト アプリケーションはシャットダウンしませんが、クライアントとの接続を閉じ、再接続する必要があります。
問題は FaultException の作成にあるようですが、問題はわかりません。
@Roeal は、おそらく faultException を同期メソッドでしか使用できないことを示唆していますが、このリンクでは、非同期メソッドで使用される例を見ることができます。私は他の例を見てきましたが、ユニークではありません。
ありがとう。
EDIT2:私は私の問題を解決します。私の問題は、FaultException では、T は自己追跡エンティティであるプロパティを持つオブジェクトであり、これは問題です。間違っていなければ、例外のプロパティとして基本型しか使用できません。
次に、例外として、ISerialize を実装しました。クライアントに情報を送信できるようにする必要があります。これがないと、クライアントは null プロパティを持つ exception.Detail を受け取ります。