繁体   English   中英

当我引发故障异常(异步方法)时,WPF自宿主应用程序中的WCF服务崩溃

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM