Pool of two objects for a web service I am creating a web service that uses a component I've licensed that is restricted to two concurrent instances at any one time. Creating a new instance of the component takes a long time (seconds) so I want to maintain a pool of objects for re-use. Here's my first (working) attempt, but it seems fairly inelegant, and also likely that I've made some mistakes (although it hasn't failed in my own tests):

public class MyWebService : System.Web.Services.WebService
{
    static RestrictedClass rc1, rc2;

    [WebMethod]
    public byte[] MyMethod(byte[] Stream1, byte[] Stream2)
    {
        RestrictedClass rc = null;
        Mutex m1 = null, m2 = null;
        if (rc1 == null)
        {
            m1 = new Mutex(true, "rc1");
            m1.WaitOne();
            rc1 = new RestrictedClass();
            rc = rc1;
        }
        else if (rc2 == null)
        {
            m2 = new Mutex(true, "rc2");
            m2.WaitOne();
            rc2 = new RestrictedClass();
            rc = rc2;
        }
        else
        {
            bool m1Granted, m2Granted;
            m1 = new Mutex(true, "rc1", out m1Granted);
            m2 = new Mutex(true, "rc2", out m2Granted);
            int idx;
            if (m1Granted)
            {
                idx = 0;
            }
            else if (m2Granted)
            {
                idx = 1;
            }
            else
            {
                idx = Mutex.WaitAny(new Mutex[] { m1, m2 });
            }
            if (idx == 0)
            {
                rc = rc1;
                m2.Close();
            }
            else if (idx == 1)
            {
                rc = rc2;
                m1.Close();
            }
        }

        Result = rc.DoStuff();

        if (m1 != null &amp;&amp; rc == rc1)
            m1.ReleaseMutex();
        if (m2 != null &amp;&amp; rc == rc2)
            m2.ReleaseMutex();
        return Result.ToArray();
    }
}


Please pick it apart and suggest any improvements you like.
I have plenty of things to say here.. 


You should apply separation of concerns by isolating the pooling behavior from the logic of the webmethod itself.
you might want to create both instances at startup
blocking inside the web methods will seriously limit throughput, consider using async methods
What happens if there is an exception and you don't release the mutex?
The pooling can be implemented much simpler using higher level concurrency features, for example a BlockingCollection:




public class ObjectPool&lt;T&gt; 
{
    private readonly BlockingCollection&lt;Lazy&lt;T&gt;&gt; _pool;

    public ObjectPool(int size, Func&lt;T&gt; constructor)
    {
        var resources = Enumerable.Repeat(new Lazy&lt;T&gt;(constructor), size);
        var stack = new ConcurrentStack&lt;Lazy&lt;T&gt;&gt;(resources);
        _pool = new BlockingCollection&lt;Lazy&lt;T&gt;&gt;(stack);
    }

    public IDisposable Aquire(out T resource)
    {
        Lazy&lt;T&gt; lazy = _pool.Take();
        resource = lazy.Value;
        return new Disposable(() =&gt; _pool.Add(lazy));
    }

    public class Disposable : IDisposable
    {
        private readonly Action _dispose;

        public Disposable(Action dispose)
        {
            _dispose = dispose;
        }

        public void Dispose()
        {
            _dispose.Invoke();
        }
    }
}


The call to Aquire will block until an item is available in the pool, it's very important to call Dispose on the returned object, this will release the resouce back into the pool. You can use try/finally or a using statement:

    private static readonly ObjectPool&lt;Random&gt; pool 
        = new ObjectPool&lt;Random&gt;(2, () =&gt; new Random());

    static int CalculateRandomNumber()
    {
        using (pool.Aquire(out var rnd))
        {
            return rnd.Next();
        }
    }


Notice how a Stack is used in combination with Lazy. This ensures that you will never create more instances than are in use at the same time.