捕获FaultException后,wcf客户端代理的Abort()方法不释放会话

Ser*_*lov 7 c# wcf faultexception

我创建了一个在IIS和wcf客户端托管的简单wcf服务,并发现当你从wcf服务捕获一个FaultException,然后调用client.Abort()来释放会话(如微软样本所说)它不会发布会话并在第11次电话会议中挂断.

这是一个例子:

Wcf服务:

[ServiceContract]  
public interface IService1
{
    [OperationContract]
    string GetData(int value);
}


public class Service1 : IService1
{
    public string GetData(int value)
    {
        throw new FaultException("Exception is here");

        return string.Format("You entered: {0}", value);
    }
}
Run Code Online (Sandbox Code Playgroud)

客户:

class Program
{
    static void Main(string[] args)
    {
        Service1Client client = null;          

        for(int i = 0; i < 15; i++)
        {
            try
            {
                client = new Service1Client();
                client.GetData(100);                   
            }
            catch (TimeoutException timeoutEx)
            {
                Console.WriteLine(timeoutEx);
                client.Abort();
            }
            catch (FaultException faultEx)
            {
                Console.WriteLine(faultEx);
                client.Abort();
            }
            catch (CommunicationException commEx)
            {
                Console.WriteLine(commEx);
                client.Abort();
            }
      }  
   }              
Run Code Online (Sandbox Code Playgroud)

}

但是如果你用client.Close()替换client.Abort()for catch(FaultException),那么一切都像魅力一样,并且在第11次调用wcf-service方法后没有锁定.

为什么会这样?为什么Abort()方法在捕获到FaultException后没有清理会话?

Mar*_*cus 6

两件事情:

  • Abort()当通信通道处于故障状态时应使用.使用Close()使客户端尝试与服务进行通信,告诉它关闭服务实例,如果愿意,可以优雅地使用.如果通信通道处于故障状态,则意味着无法从客户端到服务进行通信.在这种情况下,您应该拨打电话,Abort()以便至少关闭客户端.服务实例/会话仍将在服务器上处于活动状态(因为两者之间没有通信),并且在实例超时发生之前将保持不变.如果您已经调用Close()了故障通道,则会产生更多错误.
  • 你的服务是扔了FaultException.这并不意味着通信通道将进入故障状态.即你仍然可以使用同一个客户端拨打电话.因此,在你的例子中,你不应该打电话Abort().

tl; dr Abort()只关闭客户端.服务实例/会话仍然存在.

您可以使用以下方法检查通信通道的状态:

ICommunicationObject comObj = ((ICommunicationObject)client);
if(comObj.State == CommunicationState.Faulted)
   client.Abort();
else
   client.Close();
Run Code Online (Sandbox Code Playgroud)


小智 2

您是否尝试过我用于调用 WCF 的这种方式?

class Program
{
static void Main(string[] args)
{
    for(int i = 0; i < 15; i++)
    {
        using Service1Client client = new Service1Client()
        {
        try
        {
            client.GetData(100);                   
        }
        catch (TimeoutException timeoutEx)
        {
            Console.WriteLine(timeoutEx);
            client.Abort();
        }
        catch (FaultException faultEx)
        {
            Console.WriteLine(faultEx);
            client.Abort();
        }
        catch (CommunicationException commEx)
        {
            Console.WriteLine(commEx);
            client.Abort();
        }
        finally
        {
            client.Close();
        }
        }
  }  
}              
Run Code Online (Sandbox Code Playgroud)