2010-10-12 10 views
6

Utworzono prostą usługę wcf hostowaną w klientach IIS i wcf i zorientowałem się, że kiedy wychwycimy wyjątek FaultException z usługi wcf, a następnie wywołujemy klienta. Przerwij(), aby zwolnić sesję (jak powiedzieli próbki microsoft), nie zwalnia sesji i rozłącza się w jedenastym wywołaniu.Metoda abort() proxy klienta wcf nie zwalnia sesji po wychwyceniu wyjątku FaultException

Oto przykład:

usługi 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); 
    } 
} 

Klient:

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

}

Ale jeśli zastąpi client.Abort() z client.Close() dla catch (FaultException) wtedy wszystko działa jak czar i nie ma blokady po 11. wywołaniu wcf -usługa usługi.

Dlaczego to możliwe? Dlaczego metoda Abort() nie czyści sesji po przechwyceniu wyjątku FaultException?

+2

Czy wystarczy skopiować wklejony go stąd? http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/f86c056a-4027-453a-a46c-fc223e03589b/ – oleksii

Odpowiedz

2

Czy próbowałeś w ten sposób, które używam do wywoływania 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(); 
     } 
     } 
    } 
}    
+0

Ta odpowiedź byłaby bardziej pomocna, gdyby zawierała wyjaśnienie DLACZEGO korzystasz z tej metody . –

5

dwie rzeczy:

  • Abort() powinny być stosowane, gdy kanał komunikacji jest w stanie mu nic zarzucić. Korzystanie z usługi Close() powoduje, że klient próbuje komunikować się z usługą, mówiąc mu, aby zamknęła instancję usługi, tak, aby była pełna wdzięku. Jeśli kanał komunikacji znajduje się w stanie awaryjnym, oznacza to, że nie można wykonać komunikacji między klientem a serwisem. W takiej sytuacji należy zadzwonić pod numer Abort(), aby zamknąć co najmniej klienta . Instancja/sesja usługi będzie nadal działać na serwerze (ponieważ nie ma komunikacji między nimi) i pozostanie taka do momentu wystąpienia limitu czasu wystąpienia instancji. Jeśli zadzwoniłbyś pod numer Close() na kanale, na którym wystąpił błąd, to spowodowałoby to więcej błędów.
  • Twoja usługa rzuca FaultException. Nie oznacza to, że kanał komunikacji zostanie wprowadzony w stan błędu. np. nadal możesz dzwonić za pomocą tego samego klienta. I jako taki, w twoim przykładzie nie powinieneś dzwonić pod numer Abort().

tl; drAbort() zamyka tylko klienta. Instancja/sesja usługi wciąż żyje.

Można sprawdzić stan kanału komunikacyjnego, używając:

ICommunicationObject comObj = ((ICommunicationObject)client); 
if(comObj.State == CommunicationState.Faulted) 
    client.Abort(); 
else 
    client.Close(); 
Powiązane problemy