Why do my WCF service returning a FaultException, time out after 10 calls?
Asked Answered
O

6

9

I have a WCF service that sometimes has to return a Fault. For some reason, the calls to my service begins to time out with the following error: "The request channel timed out while waiting for a reply after 00:00:59.8906201. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout."

After examining the problem, a pattern emerged: When the service had returned a fault 10 times, the timeout starts. So I created a testservice implemented by:

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

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

This only happens, when the service is returning a FaultException. If I throw a normal exception, the service is able to continue running after the 10th call. Obviously, i would like to wrap my exceptions nicely, so just throwing normal exceptions is not a real option.

Why do I experience these timeout exceptions? Thanks in advance for any help..

Oeo answered 12/6, 2009 at 12:13 Comment(0)
O
1

Apparently, the client code should be as follows:

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

Calling client.Abort() should always be a last resort.

Oeo answered 18/6, 2009 at 9:15 Comment(0)
H
3

I don't have enough points to comment, so new response...

Self hosted services only allow a max of 10 concurrent connections - no matter the transport. If you're running WCF services inside of IIS/WAS you shouldn't have to worry about this (unless you're on XP/Vista where the max concurrent connections is also 10).

Differences between a fault exception and a regular exception in this scenario can account for the result you're seeing.

Remember, a regular unhandled exception will fault the channel. In doing so I assume this opens up an available connection. When you return a fault, it won' automatically fault the channel because it allows you to do something with the connection and handle the fault on your end because it is a possible "expected" fault whereas an unhandled exception would not be.

Even when you return a fault, you still need to Abort() the connection. Also, underneath there are unmanaged resources so be sure to implement IDisposable on your clients/proxy's callers.

Hoggish answered 12/6, 2009 at 18:58 Comment(0)
B
2

I think this might be because the default behavior of a WCF service is 10 concurrent sessions. Are you keeping the connections open after the FaultExceptions occur? You can try to alter this value in the BehaviorConfiguration (ServiceThrottling > MaxConcurrentSessions) and see if that changes anything. I suggest you use the Microsof Service Configuration Editor to check out what other values are set by default. (MSDN)

hope this helps...

Broderick answered 12/6, 2009 at 12:43 Comment(2)
But shouldn´t the client.Abort() or client.Close() close the session? And why is this only happening when using FaultException?Oeo
I have the same question as Jesper. Anyone?Chancre
N
2

I was facing the same issue. A closer look revealed that I was not closing the webservice client after I was done making the calls to the webservice. Once I did that, it did not fail even after 10 method calls to the webservice. See the example below.

WebServiceClient svcClient = new WebServiceClient();

string returnValue = svcClient.GetDocumentName(fileId);

svcClient.Close();

proper pattern:

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

ClientBase implements IDisposable, which calls Close() within the Dispose method.

Nanete answered 5/11, 2009 at 22:40 Comment(2)
You should not wrap your WCF clients with using statement. See the following article: msdn.microsoft.com/en-us/library/aa355056.aspxBetony
thanks had this issue as well, was quite difficult to trace the problem. anyway thanks for postingCaprice
E
1

I might be wrong here, but I think it has something to do with the hosting of the WCF service.

Because it might not be able to respond to the request in a timely fashion.

IIS on Windows XP, for instance, can reply to 5 (and I'm not so sure about it right now) simultaneous requests. If more requests are made, it go to a queue.

And I believe it might be loosing the requests, and doing so, not processing them, as your test actually do nothing but throw an exception.

Ens answered 12/6, 2009 at 12:19 Comment(0)
O
1

Apparently, the client code should be as follows:

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

Calling client.Abort() should always be a last resort.

Oeo answered 18/6, 2009 at 9:15 Comment(0)
R
0

Try my WCF Service Model Client API and see if the same results occur. I am think something is not right in the client code...

The Code

The PPT

Also, enable verbose WCF logging on both the client and server...

Rumanian answered 12/6, 2009 at 18:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.