3

I'm implementing a Silverlight application that uses WCF services heavily, I've got to the point now where occasionally there are several long service calls that block other service calls from running.

These service calls eventually time out. I'd like to see if its possible to a queue system that executes service calls one after another, this way long calls will hold up other calls but won't cause them to timeout.

I'm using service agents to wrap the service calls

public interface IExampleServiceAgent
{
    void ProcessData(int a, string b, EventHandler<ProcessDataCompletedEventArgs> callback);
}


Public ExampleServiceAgent1 : IExampleServiceAgent
{
     ExampleClient _Client = new ExampleClient();

     public void ProcessData(int anInt, string aString, EventHandler<ProcessDataCompletedEventArgs> callback)
     {
           EventHandler<ProcessDataCompletedEventArgs> wrapper = null;
           wrapper = (a,b) =>
           {
               callback(a,b);
               _Client.ProcessDataCompleted -= wrapper;
           }
           _Client.ProcessDataCompleted += wrapper;
           _Client.ProcessDataAsync(anInt,aString);
     }
}

The above service agent would then be called from code as follows:

ServiceAgent.ProcessData(1,"STRING", (a,b) =>
{
    if (b.Error != null)
    {
         //Handle Error
    }
    else
    { 
         //DO something with the data
    }
}

Is there a way I could put these service calls into a queue and execute them one by one?

I've tried wrapping them as Actions and adding them to a queue, but this does not wait for one to finish executing before starting the next one and although they do call the service correctly no data is returned to the calling ViewModel.

Midimatt
  • 1,114
  • 2
  • 17
  • 35
  • **Instead**, I would focus on why those calls taking so long and then finally timeout. And also why they cause **other calls** to timeout. This is not natural. – Aliostad Mar 26 '12 at 12:49
  • Aside from adding a level of queuing on the client, have you looked at turning off some of the default restrictions of WCF services on the server side? Blocking only occurs when the 2 connection limit per IP address, or MaxConcurrentConnections limit are at the defaults. The IP address limit is your first problem if you are hitting the WCF with multiple async calls. – iCollect.it Ltd Mar 26 '12 at 12:51
  • The reason some of the calls are taking a long time is the large amounts of data they have to deal with. if I happen to get 2 slow calls at the same time then there is a high chance that all other calls will timeout before the slow calls complete. @HiTechMagic is there any built in queueing within WCF to prevent blocking? – Midimatt Mar 26 '12 at 13:04
  • @Midimatt: WCF does not queue up calls. They are expected to execute immediately. Any queuing is performed server-side for long tasks. The solutions are 1) Increase the number of allowed simultaneous connections or 2) stop making so many calls (manage it client side). – iCollect.it Ltd Mar 26 '12 at 15:00
  • Can you share your WCF class's ServiceBehavior? i.e. `[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.PerSession)]` – Joel C Mar 26 '12 at 16:35
  • @HiTech Actually, WCF does queue up calls: *behavior/serviceThrottling/@maxConcurrentCalls: defines the maximum number of messages actively processed by all the service instances of a ServiceHost. The default value is 16. Calls in excess of the limit are queued.* That's where the OpenTimeout setting comes into play on the client side, that controls how long the client will let its requests sit in the service's queue waiting for acknowledgement that the request is being processed. – Joel C Mar 26 '12 at 16:42
  • @Joel C: Good to know, but he is likely hitting the IP limit (which occurs long before the throttling limits become a problem). – iCollect.it Ltd Mar 27 '12 at 09:31

1 Answers1

3

WCF services can cope with a huge number of calls but, to avoid denial of service attacks, the number of requests that can be processed is limited by default.

The significant limitations for Silverlight WCF services would be

  • A default limit of 2 simultaneous calls from the same IP address.
  • A limit of approx 10-16 concurrent connections (documentation varies on this one).

This CodeProject article on Quick Ways to Boost Performance and Scalability of ASP.NET, WCF and Desktop Clients was useful.

I am guessing you are immediately hitting the first issue. In your WCF config you need to add the following to increase the single IP connections:

<system.net> 
  <connectionManagement> 
    <add address="*" maxconnection="100" /> 
  </connectionManagement> 
</system.net>

You may then hit the second limit for which the solution is tweak the service behaviors in the web/app.config files.

Here are a few more references I found while sorting out these issues myself:

Community
  • 1
  • 1
iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
  • Increasing the max connections has stopped the timeouts which is great, I'll have to give those articles a read and see if there are any other tricks I can use. Thanks – Midimatt Mar 28 '12 at 09:21