![](/img/trans.png)
[英]WCF Service(NetTcpBinding) + host on managed WPF application
[英]WCF service in WPF self host application crash when I throw a fault exception (async methods)
我在WPF应用程序中托管了一个服务,该服务具有带有Begin / end方法的async方法,并且当我在服务中捕获异常时,我想抛出faultException来警告客户端。
但是,当我尝试引发faultException时,主机应用程序崩溃,突然关闭。
在我的存储库中,我捕获了UpdateException,然后创建了一个自定义异常UniqueKeyException,该异常将被抛出给调用者。 调用方是在Begin方法中调用的辅助方法。
此辅助方法捕获UniqyeKeyException并仅执行“抛出”,即在我的end方法的try / catch块中捕获。 这里有一些我不理解的地方,为什么最后该异常会在AgregateException块而不是UniqueKeyException块中被捕获。
好吧,无论如何,在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与synch方法一起使用,但是在此链接中,我可以看到一个与异步方法一起使用的示例。 我看过别人的例子,不是唯一的。
谢谢。
EDIT2:我解决了我的问题。 我的问题是在FaultException中,T是一个对象,该对象具有作为自我跟踪实体的属性,这是一个问题,如果我没有记错,我只能将基本类型用作异常的属性。
然后,在例外情况下,我将ISerialize植入其中。 需要能够将信息发送到客户端,否则,客户端会收到异常。Detail包含null属性。
您是否还在服务合同中声明了同步操作? 在这种情况下,这可能会有所帮助:
如果在服务操作合同上定义了故障合同,则
FaultContract
属性应仅应用于同步操作 。
-Juval Lowy,“ Programming WCF Services 3rd Edition”(第456页)
我解决了我的问题。 我的问题是在FaultException中,T是一个对象,该对象具有作为自我跟踪实体的属性,这是一个问题,如果我没有记错,我只能将基本类型用作异常的属性。
然后,在例外情况下,我将ISerialize植入其中。 需要能够将信息发送到客户端,否则,客户端会收到异常。Detail包含null属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.