我不想编写自己的书,因为恐怕我可能会错过某些东西和/或剥夺他人的工作,那么.NET库中是否存在ObjectPool(或类似的)类?
对于对象池,我的意思是一个类,该类有助于缓存需要很长时间才能创建的对象,通常用于提高性能。
最佳答案
更新:
我还要从TPL DataFlow提出 BufferBlock<T>
。 IIRC现在是.net的一部分。 BufferBlock<T>
的伟大之处在于,您可以使用 Post<T>
和 ReceiveAsync<T>
扩展方法异步等待项变得可用。在异步/等待世界中非常方便。
原始答案
前一段时间,我遇到了这个问题,并提出了一个轻量级(准备就绪)线程安全(我希望)池,该池已被证明非常有用,可重用且健壮:
public class Pool<T> where T : class
{
private readonly Queue<AsyncResult<T>> asyncQueue = new Queue<AsyncResult<T>>();
private readonly Func<T> createFunction;
private readonly HashSet<T> pool;
private readonly Action<T> resetFunction;
public Pool(Func<T> createFunction, Action<T> resetFunction, int poolCapacity)
{
this.createFunction = createFunction;
this.resetFunction = resetFunction;
pool = new HashSet<T>();
CreatePoolItems(poolCapacity);
}
public Pool(Func<T> createFunction, int poolCapacity) : this(createFunction, null, poolCapacity)
{
}
public int Count
{
get
{
return pool.Count;
}
}
private void CreatePoolItems(int numItems)
{
for (var i = 0; i < 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 > 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<T>();
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<T>) asyncResult;
return result.EndInvoke();
}
}
为了避免池对象的任何接口(interface)要求,对象的创建和重置均由用户提供的委托(delegate)执行:
Pool<MemoryStream> msPool = new Pool<MemoryStream>(() => new MemoryStream(2048), pms => {
pms.Position = 0;
pms.SetLength(0);
}, 500);
在池为空的情况下,BeginPop / EndPop对提供了一种APM(ish)手段,当一个对象可用时(使用Jeff Richter出色的AsyncResult<TResult>实现)异步检索对象。
我不太记得为什么它只限于T:class ...可能没有。
关于c# - 库中已经存在ObjectPool <T>或类似的.NET?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1698738/