views:

3980

answers:

4

I have a WCF Service and an application with a Service Reference to it, and with the application I have a loop and in each iteration it's making a call to a method in this wcf web-service.

The problem is that after about 9 calls or so, it just stops...and if you hit Pause button of VS, you will see that it's stuck on the line where it makes the call.

After some time waiting for it, this TimeoutException is thrown:

The request channel timed out while waiting for a reply after 00:00:59.9970000. 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.


I researched a bit on this, and found some solutions that involved editing the app.config in the application, and here are excerpts of it:

<serviceBehaviors>
    <behavior name="ThrottlingIssue">
        <serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" />
    </behavior>
</serviceBehaviors>

.

<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" 
 maxArrayLength="2147483647" 
 maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />

Then, after I stop debugging, after a couple of minutes, an error message pops up telling me that a Catastrophic failure has occurred.

How can I fix this problem? I did not have this issue when I was working with a normal Web Service.


For reference, here is the whole app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="ThrottlingIssue">
                    <serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IDBInteractionGateway" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
        <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
                        maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Message">
                        <transport clientCredentialType="Windows" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Windows" negotiateServiceCredential="true"
                            algorithmSuite="Default" establishSecurityContext="true" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:28918/DBInteractionGateway.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDBInteractionGateway"
                contract="DBInteraction.IDBInteractionGateway" name="WSHttpBinding_IDBInteractionGateway">
                <identity>
                    <dns value="localhost" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>


[Update] Solution:

Apparently, after each request you have to Close the connection...I am now closing the connection after each request and it's working like a charm.

Although what I still can't understand is that in my app.config, I set my maxConcurrentCalls and maxConcurrentSessions to 500, and yet, I can only make 10. Anyone has any answer for that one? (maybe I have something wrong in my app.config posted above)

The answer for the above question (now dashed) is because I was editing the client app.config, not the service config file (web.config)

+1  A: 

Can you configure tracing and run the loop? It may be that the channel is becoming faulted and causing the client to time out.

JP Alioto
+10  A: 

The default number of allowed concurrent connections is 10.
Most likely your client is not closing the connections.

To increase the number of concurrent calls, you will have to add your behavior to the service configuration, not the client.

markt
In my app.config, I set my maxConcurrentCalls and maxConcurrentSessions to 500, and yet, I can only make 10. Is there something wrong with my app.config?
Andreas Grech
Did you set the serviceBehavior on the service element to use the behavior configuration.
markt
It looks like you posted the client app.config ? - you will need to change the service config..
markt
But I don't have an app.config file in my WCF project. Should there be one?
Andreas Grech
How are you hosting it? .. if in IIS, it could be in web.config.
markt
Ah yes, it is infact in the web.config. Fixed it now. Thanks for your help.
Andreas Grech
No problem - glad to help.
markt
The term 'connection' is a little confusing here, but I almost can't wait to update all my code tomorrow. This was driving me crazy during testing.
Thorarin
allowed concurrent connections is not enough. he still need to close connections.
Eduardo Xavier
A: 

I ran into this problem this week and I wasn't able to quite figure out what was going on. I actually did change my call to my service to Dispose() the service client, but it didn't seem to have any effect. Apparently, there was another service call lurking somewhere.

What may be interesting to note is what made me decide that this was not the problem: this limit is not related to the actual number of socket connections to the webservice. When you hit the maxConcurrentSessions limit, there is still only one actual socket connection. I was checking this with netstat, which brought me to the wrong conclusion. So, don't confuse sessions with sockets.

We have interfaces defined for all our WCF services, so I'm planning to adapt this pattern in my code now:

IMyService service = new MyServiceClient();
using (service as IDisposable)
{
    service.MyServiceMethod();
}

What's also interesting, is that the problem did not occur for me when the services (and website) were hosted on IIS. The configuration is (almost) identical, yet I could not reproduce this behavior on that machine. I guess that's a good thing :)

@ John Saunders (about variable assignment in using):

I usually do put the variable assignment in the using statement. But the IMyService that's generated is not implicitly convertible to IDisposable. If you really wanted the assignment in there, I suppose the alternative would be:

IService service;
using ((service = new ServiceClient()) as IDisposable)
{
}

That still leaves the problem of the variable scope being wrong though. The reference to IService service is unusable, but still in scope. So this would be better in that respect:

using (IDisposable serviceDisposable = new ServiceClient())
{
     IService service = (IService)serviceDisposable;
}

That requires me to introduce an extra variable name though. *Meh*

Thorarin
Why not put the assignment into the using block as well?
John Saunders
Also, see http://www.iserviceoriented.com/blog/post/Indisposable+-+WCF+Gotcha+1.aspx.
John Saunders
I normally do, but `using (IMyService service = new MyServiceClient())` does not work (*type used in a using statement must be implicitly convertible to 'System.IDisposable'*). Doing both assignment and casting inside the `using` seemed a little messy to me.
Thorarin
The delegate solution in that article is sort of elegant, but I'm not sure if my code snippet above warrants such a solution. It's not very likely that that execution will be interrupted in between those lines, unless your app dies?
Thorarin
`using (var service = new ServiceClient())`
John Saunders
That works yes, but I like to be more explicit about my types, if it's not immediately evident from the code already.
Thorarin
A: 

This can be solved by creating singleton class as interface between web service reference and application. Then it will create only one instance of service reference.

class ServiceInterface

{

 private static ServiceInterface  _instance;

 private ServiceClient _service = new ServiceClient ;



private ServiceInterface()

{

   //Prevent accessing default constructor

}

public static ServiceInterface GetInstance()

{

 if(_instance == null)

 {

  _instance = new ServiceInterface();

}

    return _instance;

}

// You can add your functions to access web service here

Public int PerformTask()
{
     return _service.PerformTask();
}

}

Suranga Bandara