How to monitor/wait on array of objects?

Extending the msdn example found here:

public class FiniteObjectPool<T>: IDisposable
{
    System.Threading.AutoResetEvent m_Wait = new System.Threading.AutoResetEvent(false);

    private ConcurrentBag<T> _objects;

    public FiniteObjectPool()
    {
        _objects = new ConcurrentBag<T>();
    }

    public T GetObject()
    {
        T item;
        while(!_objects.TryTake(out item))
        {
            m_Wait.WaitOne(); //an object was not available, wait until one is
        }

        return item;
    }

    public void PutObject(T item)
    {
        _objects.Add(item);
        m_Wait.Set(); //signal a waiting thread that object may now be available
    }

    public void Dispose()
    {
        m_Wait.Dispose();
    }
}

EDIT – example usage with ‘Context’ idiom wrapper

class Program
{
    public class FiniteObjectPoolContext<T>: IDisposable
    {
        FiniteObjectPool<T> m_Pool = new FiniteObjectPool<T>();
        public T Value { get; set; }

        public FiniteObjectPoolContext(FiniteObjectPool<T> pool)
        {
            m_Pool = pool;
            Value = pool.GetObject(); //take an object out - this will block if none is available
        }

        public void Dispose()
        {
            m_Pool.PutObject(Value); //put the object back because this context is finished
        }
    }
    static void Main(string[] args)
    {
        FiniteObjectPool<int> pool = new FiniteObjectPool<int>();

        for (int i = 0; i < 10; i++)
        {
            pool.PutObject(i);
        }

        List<Task> tasks = new List<Task>();
        for (int i = 0; i < 20; i++)
        {
            int id = i;
            tasks.Add(Task.Run(() =>
                {
                    Console.WriteLine("Running task " + id);
                    using (var con = new FiniteObjectPoolContext<int>(pool))
                    {
                        Console.WriteLine("Task " + id + " got object from pool: " + con.Value);
                        System.Threading.Thread.Sleep(5000);
                        Console.WriteLine("Task " + id + " is finished with pool object: " + con.Value);
                    }
                }));
        }

        Task.WaitAll(tasks.ToArray());
        Console.WriteLine("DONE");
        Console.ReadLine();
    }
}

Notice the latency injected by the thread synchronization mechanisms.

Leave a Comment