在出现故障后重新使用WCF中的客户端类

时间:2009-05-01 12:17:55

标签: wcf

我将WCF用于客户端服务器系统。 当我在服务器上向IService添加服务引用时,会生成代理类ServiceClient。 我的代码如下所示:

ServiceClient client = new ServiceClient();
try
{
    client.Operation1();
}
catch(Exception ex)
{
    // Handle Exception
}
try
{
    client.Operation2();
}
catch(Exception ex)
{
    // Handle Exception
}

问题是如果第一次调用中存在通信异常,则客户端的状态将更改为Faulted,并且我不知道如何重新打开它以进行第二次调用。有没有办法重新打开它?或者我应该创建一个新的并替换实例(它似乎不是一种优雅的方式)?

4 个答案:

答案 0 :(得分:16)

一旦ICommunicationObject(您的WCF客户端对象)处于故障状态,“重新打开”它的唯一方法是创建一个新的。

ServiceClient client = new ServiceClient();
try
{
    client.Operation1();
}
catch(Exception ex)
{
    if (client.State == CommunicationState.Faulted)
    {
            client.Abort();
            client = new ServiceClient();
    }
}
try
{
    client.Operation2();
}
catch(Exception ex)
{
   // Handle Exception
}

答案 1 :(得分:5)

如果在第一次调用中存在导致故障状态的通信异常,则必须基本上“重新创建”WCF客户端代理。在你的例子中,我可能会做类似的事情:

if (client.State == CommunicationState.Faulted)
    client = new ServiceClient();

如果连接出现故障,这将允许您“重新打开”连接。这可能看起来有点矫枉过正,但如果你在客户端获得通信异常,可能还有其他事情发生(即:服务器死了?服务器无响应?)

祝你好运

答案 2 :(得分:4)

同意最后的答案,一旦失败,你需要中止。我们使用lambdas和类似下面的方法的组合来执行此操作:

  public static void Use<TServiceInterface>(TServiceInterface proxy, Action handler)
  {
     Type proxyType = typeof(TServiceInterface);
     IClientChannel channel = (IClientChannel)proxy;

     try
     {
        handler();

        _logSource.Log(LogLevel.Debug, string.Format("Closing client channel for '{0}' ...", proxyType.Name));

        channel.Close();

        _logSource.Log(LogLevel.Debug, string.Format("Client channel for '{0}' closed.", proxyType.Name));
     }
     catch
     {
        if (channel.State == CommunicationState.Faulted)
        {
           _logSource.Log(LogLevel.Debug, string.Format("Aborting client channel for '{0}' ...", proxyType.Name));

           channel.Abort();

           _logSource.Log(LogLevel.Debug, string.Format("Client channel for '{0}' aborted.", proxyType.Name));
        }
        else
        {
           _logSource.Log(LogLevel.Debug, string.Format("Closing client channel for '{0}' ...", proxyType.Name));

           channel.Close();

           _logSource.Log(LogLevel.Debug, string.Format("Client channel for '{0}' closed.", proxyType.Name));
        }

        throw;
     }
  }

这是对.net上已经存在的解决方案的略微修改,但它对于处理代理非常有用。然后,您可以在同一个lambda表达式中放置多个服务调用,并将其传递给方法。

答案 3 :(得分:0)

这很可能是由服务器端的未处理异常引起的。默认情况下,WCF运行时会终止您的服务实例,并在未处理的异常情况下将通道置于故障状态,并且您无法再通过该通道进行通信。因此,您需要与服务建立新会话。您应该在服务器端捕获异常并通过引发FaultException或定义FaultContract来发送soap错误。您还可以使用returnUnknownExceptionsAsFaults服务行为。