Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>UPDATE:</p> <p>I'd also put forward <a href="http://msdn.microsoft.com/en-us/library/hh160414.aspx" rel="noreferrer"><code>BufferBlock&lt;T&gt;</code></a> from TPL DataFlow. IIRC it's part of .net now. The great thing about <code>BufferBlock&lt;T&gt;</code> is that you can wait asynchronously for items to become available using the <a href="http://msdn.microsoft.com/en-us/library/hh194836.aspx" rel="noreferrer"><code>Post&lt;T&gt;</code></a> and <a href="http://msdn.microsoft.com/en-us/library/hh194760.aspx" rel="noreferrer"><code>ReceiveAsync&lt;T&gt;</code></a> extension methods. Pretty handy in an async/await world.</p> <p>ORIGINAL ANSWER</p> <p>A while back I faced this problem and came up with a lightweight (rough'n'ready) threadsafe (I hope) pool that has proved very useful, reusable and robust:</p> <pre><code> public class Pool&lt;T&gt; where T : class { private readonly Queue&lt;AsyncResult&lt;T&gt;&gt; asyncQueue = new Queue&lt;AsyncResult&lt;T&gt;&gt;(); private readonly Func&lt;T&gt; createFunction; private readonly HashSet&lt;T&gt; pool; private readonly Action&lt;T&gt; resetFunction; public Pool(Func&lt;T&gt; createFunction, Action&lt;T&gt; resetFunction, int poolCapacity) { this.createFunction = createFunction; this.resetFunction = resetFunction; pool = new HashSet&lt;T&gt;(); CreatePoolItems(poolCapacity); } public Pool(Func&lt;T&gt; createFunction, int poolCapacity) : this(createFunction, null, poolCapacity) { } public int Count { get { return pool.Count; } } private void CreatePoolItems(int numItems) { for (var i = 0; i &lt; numItems; i++) { var item = createFunction(); pool.Add(item); } } public void Push(T item) { if (item == null) { Console.WriteLine("Push-ing null item. ERROR"); throw new ArgumentNullException(); } if (resetFunction != null) { resetFunction(item); } lock (asyncQueue) { if (asyncQueue.Count &gt; 0) { var result = asyncQueue.Dequeue(); result.SetAsCompletedAsync(item); return; } } lock (pool) { pool.Add(item); } } public T Pop() { T item; lock (pool) { if (pool.Count == 0) { return null; } item = pool.First(); pool.Remove(item); } return item; } public IAsyncResult BeginPop(AsyncCallback callback) { var result = new AsyncResult&lt;T&gt;(); result.AsyncCallback = callback; lock (pool) { if (pool.Count == 0) { lock (asyncQueue) { asyncQueue.Enqueue(result); return result; } } var poppedItem = pool.First(); pool.Remove(poppedItem); result.SetAsCompleted(poppedItem); return result; } } public T EndPop(IAsyncResult asyncResult) { var result = (AsyncResult&lt;T&gt;) asyncResult; return result.EndInvoke(); } } </code></pre> <p>In order to avoid any interface requirements of the pooled objects, both the creation and resetting of the objects is performed by user supplied delegates: i.e.</p> <pre><code>Pool&lt;MemoryStream&gt; msPool = new Pool&lt;MemoryStream&gt;(() =&gt; new MemoryStream(2048), pms =&gt; { pms.Position = 0; pms.SetLength(0); }, 500); </code></pre> <p>In the case that the pool is empty, the BeginPop/EndPop pair provide an APM (ish) means of retrieving the object asynchronously when one becomes available (using Jeff Richter's excellent <a href="http://msdn.microsoft.com/en-us/magazine/cc163467.aspx" rel="noreferrer">AsyncResult&lt;TResult&gt;</a> implementation).</p> <p>I can't quite remember why it is constained to T : class... there's probably none.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload