2009-06-12 9 views
8

Mam usługę WCF, która czasami musi zwrócić błąd. Z jakiegoś powodu połączenia z moją usługą kończą się z powodu następującego błędu: "Kanał żądania przekroczył limit czasu oczekiwania na odpowiedź po 00: 00: 59.8906201. Zwiększ wartość limitu czasu przekazanego do połączenia z żądaniem lub zwiększ wartość Wartość SendTimeout na powiązaniu Czas przydzielony na tę operację mógł być częścią dłuższego limitu czasu. "Dlaczego moja usługa WCF zwraca wyjątek FaultException, limit czasu po 10 wywołaniach?

Po przeanalizowaniu problemu pojawił się wzorzec: po 10-krotnym zwrocie usługi nastąpiło przekroczenie limitu czasu. Więc stworzyłem testservice realizowany przez:

public string GetData(int value) 
{ 
    throw new FaultException("A testerror occured"); 
} 

a testclient:

protected void RunTestGetData() 
    { 
     using (TestServiceReference.Service1Client client 
      = new WSPerformanceTester.TestServiceReference.Service1Client()) 
     { 
      try 
      { 
       client.GetData(1); 
       client.Close(); 
       outputWriter.WriteLine(string.Format("Call run in thread {0}: GetData()", Thread.CurrentThread.ManagedThreadId)); 
       outputWriter.Flush(); 
      } 
      catch (Exception e) 
      { 
       client.Abort(); 
       client.Close(); 
       outputWriter.WriteLine(string.Format("Error occured in thread {0}: GetData(): {1}", Thread.CurrentThread.ManagedThreadId, e.Message)); 
       outputWriter.Flush(); 
      } 
     } 
    } 

tylko to się stanie, gdy usługa jest zwrócenie FaultException. Jeśli wyrzucę normalny wyjątek, usługa będzie mogła kontynuować działanie po 10. rozmowie. Oczywiście, chciałbym ładnie opakować moje wyjątki, więc zwyczajne rzucanie normalnych wyjątków nie jest realną opcją.

Dlaczego występują wyjątki timeout? Z góry dziękuję za pomoc.

Odpowiedz

1

Wydaje się, że kod klienta powinna być następująca:

protected void RunTestGetData() 
{ 
    TestServiceReference.Service1Client client 
     = new WSPerformanceTester.TestServiceReference.Service1Client() 
    try 
    { 
     client.GetData(1); 
    } 
    catch (FaultException e) 
    { 
     //Handle fault 
    } 
    try 
    { 
     if (client.State != System.ServiceModel.CommunicationState.Faulted) 
     { 
      client.Close(); 
     } 
    } 
    catch(Exception e) 
    { 
     outputWriter.WriteLine("Error occured in Client.Close()"); 
     outputWriter.Flush(); 
     client.Abort(); 
    } 
} 

Wywołanie client.Abort() powinna być zawsze ostatecznością.

+2

[potrzebne źródło] – piers7

1

Może się mylę, ale myślę, że ma to coś wspólnego z hostingiem usługi WCF.

Ponieważ może nie być w stanie odpowiedzieć na żądanie w odpowiednim czasie.

Usługi IIS w systemie Windows XP mogą na przykład odpowiedzieć na 5 (i nie jestem już tego pewien) w tej chwili). Jeśli zostanie utworzonych więcej żądań, przejdzie do kolejki.

Sądzę, że może to oznaczać utratę żądań, a co za tym idzie, nie przetwarzanie ich, ponieważ test faktycznie nie robi nic poza zgłoszeniem wyjątku.

2

Myślę, że może tak być, ponieważ domyślne zachowanie usługi WCF to 10 jednoczesnych sesji. Czy połączenia są otwarte po wystąpieniu usterek? Możesz spróbować zmienić tę wartość w BehaviorConfiguration (ServiceThrottling> MaxConcurrentSessions) i sprawdzić, czy to coś zmieni. Proponuję użyć Edytora konfiguracji usług Microsoftu, aby sprawdzić, jakie inne wartości są ustawione domyślnie. (MSDN)

nadzieję, że to pomaga ...

+0

Ale czy nie klient.Abort() czy klient.Close() zamknąć sesję? Dlaczego tak się dzieje tylko podczas korzystania z wyjątku FaultException? –

+0

Mam takie samo pytanie jak Jesper. Ktoś? –

+1

Zobacz odpowiedź @ Jarrod268 dla wyjaśnienia ... dzięki! – RoelF

0

Spróbuj mój klient usługi WCF model API i sprawdzić, czy występują takie same wyniki. Jestem że coś jest nie tak w kodzie klienta ...

The Code

The PPT

także włączyć pełne rejestrowanie WCF zarówno klientem i serwerem ...

3

I don” t ma wystarczającą ilość punktów do komentowania, więc nowa odpowiedź ...

Usługi hostowane tylko pozwalają na maksymalnie 10 równoczesnych połączeń - bez względu na transport. Jeśli korzystasz z usług WCF wewnątrz IIS/WAS, nie powinieneś się o to martwić (chyba, że ​​używasz XP/Vista, gdzie maksymalne równoczesne połączenia to 10).

Różnice między wyjątkiem błędu i zwykłym wyjątkiem w tym scenariuszu mogą uwzględniać wynik, który widzisz.

Pamiętaj, że zwykły nieobsługiwany wyjątek spowoduje uszkodzenie kanału. Zakładam, że otworzy to dostępne połączenie. Kiedy zwrócisz błąd, wygrywa on automatycznie "automatycznie" na kanale, ponieważ pozwala ci to zrobić coś z połączeniem i obsłużyć błąd na twoim końcu, ponieważ jest to możliwe "oczekiwane" uszkodzenie, podczas gdy nieobsługiwany wyjątek by nie był.

Nawet po zwrocie błędu nadal trzeba przerwać połączenie(). Ponadto pod spodem znajdują się zasoby niezarządzane, więc upewnij się, że implementujesz IDisposable na swoich klientach/dzwoniących z serwera proxy.

2

Miałem do czynienia z tym samym problemem. Bliższe spojrzenie ujawniło, że nie zamykałem klienta usługi internetowej po tym, jak wykonałem połączenia z serwisem internetowym. Kiedy to zrobiłem, nie zawiodło to nawet po 10 wywołaniach metod w serwisie internetowym. Zobacz przykład poniżej.

WebServiceClient svcClient = new WebServiceClient(); 

string returnValue = svcClient.GetDocumentName(fileId); 

svcClient.Close(); 

właściwy wzór:

using(WebServiceClient svcClient = new WebServiceClient()) 
{ 
    return svcClient.GetDocumentName(fileId); 
} 

ClientBase realizuje IDisposable, co wymaga Close() w sposobie Dispose.

+3

Nie powinieneś zawijać klientów WCF za pomocą instrukcji using. Zobacz następujący artykuł: http://msdn.microsoft.com/en-us/library/aa355056.aspx –

+0

dzięki, że również ten problem, było dość trudno prześledzić problem. w każdym razie dzięki za publikację – zulucoda

Powiązane problemy