2

I have an asp.net app that calls a WCF service. I've been having intermittent timeouts for a while so I decided to create a trace log. After getting a timeout I found the message below in the log file:

The system hit the limit set for throttle 'MaxConcurrentSessions'. Limit for this throttle was set to 10. Throttle value can be changed by modifying attribute 'maxConcurrentSessions' in serviceThrottle element or by modifying 'MaxConcurrentSessions' property on behavior ServiceThrottlingBehavior.

The thing is though I'm closing the client connection each time so I don't understand why the concurrent sessions are adding up. Below is a typical call that I make:

    try
    {
        //create proxy
        client = new CAEServiceContractClient();

        response = client.GetSecurityRecords(item); 
        totalRecords = response.TotalRecords;

        securityListView.DataSource = response.SecurityItemColl; 
        securityListView.DataBind();

        // Always close the client.
        client.Close();
        success = true;
    }
    finally
    {
        if (!success)
        {
            client.Abort();
        }
    }

So my question is, why isn't the session being destroyed once I execute client.Close()?

TIA.

Ciarán Bruen
  • 5,221
  • 13
  • 59
  • 69

1 Answers1

1

I don't see success declared in the above code as a local variable, nor do I see you setting it to false. Could it be a class member that is being set to true on the first successful call and then staying that way?

In any case, that whole code block can be rewritten to be simpler to understand (and less bug-prone) like this:

using (var client = new CAEServiceContractClient())
{
    response = client.GetSecurityRecords(item); 
    totalRecords = response.TotalRecords;

    securityListView.DataSource = response.SecurityItemColl; 
    securityListView.DataBind();
}

The using statement ensures that when the using block has completed (normally or abnormally by an exception), the client variable will be disposed (.Dispose() will be called), thus closing the connection.

EDIT: As Ladislav Mrnka pointed out, the .Dispose() method of ClientBase has a bad habit of throwing an exception in some cases. Make sure to implement the .Dispose() method in your partial CAEServiceContractClient class as described here.

Community
  • 1
  • 1
Allon Guralnek
  • 15,813
  • 6
  • 60
  • 93
  • 3
    @Allon: This is WCF anti-pattern! http://omaralzabir.com/do-not-use-using-in-wcf-client/ – Ladislav Mrnka Jan 20 '11 at 20:33
  • @Ladislav: It's not an anti-pattern, it's simply bad design of the `ClientBase` class (read the first three comments of the article you linked). But thanks for bringing it to my attention, I didn't know about it. I still like [Matt's suggestion](http://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-the-wcf-client-using-block-issue/1424384#1424384) better. – Allon Guralnek Jan 20 '11 at 21:31
  • @Allon: Yes that suggestion is very nice solution. I was not able to find it when posting my first comment. Here is official MSDN article: http://msdn.microsoft.com/en-us/library/aa355056.aspx – Ladislav Mrnka Jan 20 '11 at 22:54
  • @Allon I have declared 'bool success = false' outside that block of code I just didn't show it above – Ciarán Bruen Jan 21 '11 at 00:41
  • @Ciaran: OK, but since it doesn't have a catch block, if an exception is raised it won't be set to false. – Allon Guralnek Jan 21 '11 at 09:31
  • @Allon: The success variable is false by default, it's only set to true when client.Close is called. Does this make sense? – Ciarán Bruen Jan 21 '11 at 09:54
  • @Allon: Also, is try/catch/finally sufficient to handle the closing of the proxy? Why would we go to the trouble of adding a .Dispose method in the CAEServiceContractClient class if try/catch/finally works? Thnx for the help. – Ciarán Bruen Jan 21 '11 at 10:26
  • 1
    @Ciaran: If `success` is a local variable, then there's problem. If it's a field or property, then you need to set it to false. As for try-catch-finally, it is sufficient, but only if you do it correctly. It is very easy to get it wrong, and why I think the `using` statement is much better in general, and only somewhat better with WCF's `ClientBase` in particular (due to it throwing exceptions when disposing). – Allon Guralnek Jan 21 '11 at 11:33