Q:

Managing and Restricting the Number of API Sessions

I'm working with a WSDL API that has a limit of 100 sessions at any time. I'm using C#, so this means in my application I can only ever have in existence 100 instances of the WSSession class, otherwise the API will reject calls.
What is the best way that I could approach this? I'm working in a large application that could easily hit the 100 session limit. I don't want to throw an error when the session limit is hit, instead I'd rather block until a session is available.

A:

You can route all your remote calls through a single service where you keep a counter of how many operations are taking place at the time when the call happens. 
You can use a Semaphore to control concurrency on a given block.
Assuming you have a proxy service created for the external webservice you could create a service like this to handle all calls.
I´m also assuming you are using inversion of control, so you need to be sure there is only a single instance of this service handling all calls. 
There are alternatives to this;

moving the semaphore out and making that the singleton
or by giving the semaphore a name.

Service:
 public class PooledService 
 {
     private readonly Semaphore _semaphore;   
     private readonly WebService _service;

     public PooledService(WebService service, int max) 
     {
         _semaphore = new Semaphore(max, max);
         _service = service;
     }   

     public R Execute<R>(Func<WebService, R> expression) 
     {  
        //will block if concurrency is at maximum, waiting up to 5 seconds 
        //if you want to wait forever, then just call _semaphore.WaitOne();
        if (!_semaphore.WaitOne(5000)) 
            throw new Exception("Timed Out"); 

        try 
        {
            return expression(_service);
        } 
        finally 
        {
           _semaphore.Release();
        }
    }

     public void Execute(Action<WebService> expression) 
     {  
        //will block if concurrency is at maximum, waiting up to 5 seconds 
        //if you want to wait forever, then just call _semaphore.WaitOne();
        if (!_semaphore.WaitOne(5000)) 
            throw new Exception("Timed Out"); 

        try 
        {
            expression(_service);
        } 
        finally 
        {
           _semaphore.Release();
        }
    }
}

you can use it in this way;
var service = new PooledService(new WebService(), 100); //maximum of 100 concurrent calls
var response = service.Execute(s => s.SomeRemoteCall(...));

