tags:

views:

322

answers:

3

I've wrapped my wcf client in a IDisposable wrapper and everything appears to work correctly, I have a test case that runs this x times after around 10 times I start to get timeout's

The calling code has the helper wrapped in a using statement, so tbh I'm at a bit of a loss

Anyone shed any light on this?

public class CrmServiceHelper : IDisposable
{
    private CrmServices.CRMServicesClient client;

    public CrmServices.CRMServicesClient GetClient
    {
        get
        {
            lock (this)
            {
                if (client == null)
                    client = new CrmServices.CRMServicesClient();
            }
            return client;
        }
    }
    public void Dispose()
    {
        try
        {
            client.Close();
        }
        catch (CommunicationException ex)
        {
            client.Abort();
        }
        catch (TimeoutException ex)
        {
            client.Abort();
        }
    }
}

Sample usage code:

    using (CrmServiceHelper client = new CrmServiceHelper())
    {
        AListReponse resp = client.GetClient.GetAList(companyId);
        if ((resp != null) && (resp.AList != null))
        {
            return resp.AList ;
        }
        else
        {
            return null;
        }
    }

Service config

A: 

I don't see anything wrong with the code (though I'd test for null first, before doing the lock, in addition to after the lock).

Perhaps the problem is not with the client side, but with the service?

John Saunders
+2  A: 

After about 10 times.... that almost sounds as if you're hitting a server throttling limit.... maybe you're not properly closing your client proxy? Client sessions are hanging around, and the service won't accept any new incoming requests?

How does your service hosting look like? IIS? Self-Hosted? Are you using a per-call model, or session-based calls?

Can you show us the server side config, and the code to host the service (if you're self-hosting, that is). That might help us find a reason.

Marc

UPDATE:
if you're using "out-of-the-box-no-changes" mode, you'll have the wsHttpBinding, and you'll be using a session-based approach. The service is limited to a maximum of 10 sessions by default.

You can do two things:

1) You could change the service throttling behavior on your server side to allow more than 10 sessions at once:

   <behaviors>
      <serviceBehaviors>
        <behavior name="Throttled">
          <serviceThrottling 
            maxConcurrentCalls="25" 
            maxConcurrentSessions="25" 
            maxConcurrentInstances="25" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

Be aware this puts more strain on your server - you don't want to go too high....

2) you could change the calling model to "per-call" by adorning your service implementation with this attribute:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
class YourService : IYourService
{
 ......
}

But even in this case, the service throttling might kick in - the service is limited to 16 concurrent calls by default - you might need to increase that (and the MaxInstances, too, to the same number).

marc_s
the service config is completely default nothing added or changed at all.
RubbleFord
This would assume he was leaking connections... his IDisposable implementation should avoid this.
Anderson Imes
Although I suppose it could be a problem if the test wasn't single-threaded?
Anderson Imes
A: 
        for (int j = 0; j < 100; j++)
        {
            using (var client = new ServiceClient())
            {
                client.Method();
            }
         }

I get a time out with this code. The call takes 1 second, but after 60 calls it times out at the 1 minute time out. I close the connection inside the loop, so why does it add the calls together

Richard
I believe WCF services clients should not be wrapped inside a using statement. See the code posted at the top. http://msdn.microsoft.com/en-us/library/aa355056.aspx
RubbleFord