Метод abort () прокси-клиента wcf не освобождает сеанс после перехвата FaultException - PullRequest
7 голосов
/ 12 октября 2010

Я создал простую службу wcf, размещенную в IIS и клиенте wcf, и выяснил, что когда вы ловите FaultException из службы wcf, а затем вызываете client.Abort (), чтобы освободить сессию (как сказали образцы Microsoft) не освобождает сеанс и зависает на 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);
    }
}

Клиент:

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();
            }
      }  
   }              

}

Но если вы замените client.Abort () на client.Close () для catch (FaultException), тогда все будет работать как чудо, и после 11-го вызова метода wcf-service блокировки не будет.

Почему это может быть? Почему метод Abort () не очищает сеанс после перехвата FaultException?

Ответы [ 2 ]

6 голосов
/ 01 марта 2012

Две вещи:

  • Abort() следует использовать, когда канал связи находится в состоянии неисправности. Использование Close() заставляет клиента пытаться связаться со службой, приказывая ему закрыть экземпляр службы, как изящно, если хотите. Если канал связи находится в состоянии сбоя, это означает, что связь между клиентом и службой невозможна. В этой ситуации вы должны позвонить Abort(), чтобы как минимум клиент был закрыт. Экземпляр / сеанс службы все еще будет активен на сервере (поскольку между ними нет связи) и будет оставаться таковым до истечения времени ожидания экземпляра. Если бы вы вызвали Close() на неисправном канале, это вызвало бы больше ошибок.
  • Ваш сервис выбрасывает FaultException. Это не означает, что канал связи будет переведен в неисправное состояние. то есть вы все еще можете совершать звонки, используя один и тот же клиент. И как таковой, в вашем примере вы не должны звонить Abort().

tl; dr Abort() только закрывает клиента. Экземпляр / сеанс службы все еще жив.

Вы можете проверить состояние канала связи, используя:

ICommunicationObject comObj = ((ICommunicationObject)client);
if(comObj.State == CommunicationState.Faulted)
   client.Abort();
else
   client.Close();
2 голосов
/ 27 сентября 2011

Вы пробовали этот способ, который я использую для вызова 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();
        }
        }
  }  
}              
...