【问题标题】:WCF service in WPF self host application crash when I throw a fault exception (async methods)当我抛出错误异常(异步方法)时,WPF 自托管应用程序中的 WCF 服务崩溃
【发布时间】:2012-05-19 20:23:39
【问题描述】:

我有一个托管在 WPF 应用程序中的服务,该服务带有一个带有 Begin/end 方法的异步方法,当我在服务中捕获异常时,我想抛出一个 faultException 来警告客户端。

但是,当我尝试抛出 faultException 时,主机应用程序崩溃,突然关闭。

在我的存储库中,我捕获了 UpdateException,然后,我创建了一个自定义异常 UniqueKeyException,它被抛出给调用者。调用者是在Begin方法中调用的辅助方法。

这个辅助方法,捕获 UniqyeKeyException 并且只做一个“抛出”,即在我的 end 方法的 try/catch 块中捕获。这里有一些我不明白的地方,为什么最后这个异常是在AgregateException而不是UniqueKeyException的块中捕获的。

好吧,无论如何,在结束方法的catch块中,在AgregateException块中,我检查innerException是否为UniqueKeyException,如果是,我创建一个对象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 时崩溃。

我在post 中看到,解决方案也是在主机应用程序中捕获异常,而不仅仅是在服务对象中。但是,此解决方案使用属于 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 与同步方法一起使用,但在此 link 我可以看到一个与异步方法一起使用的示例。我见过别人的例子,不是唯一的。

谢谢。

EDIT2:我解决了我的问题。我的问题是,在 FaultException 中,T 是一个对象,它具有一个自跟踪实体的属性,这是一个问题,如果我没记错的话,我只能使用基本类型作为异常的属性。

然后,在例外情况下,我实现了 ISerialize。需要能够将信息发送给客户端,否则,客户端会收到异常。具有空属性的详细信息。

【问题讨论】:

  • 请不要将解决方案编辑到您的问题中或在标题中添加“已解决”。发布解决方案作为答案。然后您可以接受它(经过短暂的延迟),这将表明问题已解决。

标签: wpf wcf exception-handling


【解决方案1】:

您是否也在服务合同中声明了同步操作?在这种情况下,也许这会有所帮助:

如果在服务操作合同上定义了故障合同,则应仅在同步操作上应用FaultContract 属性
-- Juval Lowy,“编程 WCF 服务第三版”(p456)

【讨论】:

  • 谢谢,尽管在我读到的某些站点中,可以将 faultException 与异步方法一起使用。我在我的帖子中添加了指向其中一个的链接,在 edit1 中。谢谢。
  • 我认为他的意思是 if 您在服务合同中定义了 both 操作(因此同步和异步),那么属性应该在同步操作上
  • 就我而言,我没有同步版本的方法,我只有异步。
【解决方案2】:

我解决了我的问题。我的问题是,在FaultException中,T是一个对象,它有一个自跟踪实体的属性,这是一个问题,如果我没记错的话,我只能使用基本类型作为异常的属性。

然后,在例外情况下,我实现了 ISerialize。需要能够将信息发送给客户端,否则,客户端会收到异常。具有空属性的详细信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多