我不想写我自己的,因为我担心我可能会遗漏一些东西和/或抄袭别人的工作,那么.NET的库中是否存在一个ObjectPool (或类似的)类?
通过对象池,我指的是帮助缓存需要很长时间才能创建的对象的类,通常用于提高性能。
发布于 2009-11-09 10:44:40
更新:
我也从第三方物流DataFlow提出了BufferBlock。IIRC它现在是.net的一部分。BufferBlock<T>的伟大之处在于,您可以使用Post和ReceiveAsync扩展方法异步等待项目变为可用。在异步/等待的世界中非常方便。
原始答案
不久前,我遇到了这个问题,并提出了一个轻量级(粗略的) threadsafe (我希望)池,它被证明非常有用,可重用和健壮:
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();
}
}为了避免池化对象的任何接口要求,对象的创建和重置都是由用户提供的委托执行的:
Pool<MemoryStream> msPool = new Pool<MemoryStream>(() => new MemoryStream(2048), pms => {
pms.Position = 0;
pms.SetLength(0);
}, 500);在池为空的情况下,BeginPop/EndPop对提供了一种异步检索对象的方法(使用Jeff Richter出色的AsyncResult实现)。
我不太记得为什么它被限制在T: class...可能什么都没有。
发布于 2009-11-09 12:08:08
在即将发布的.NET (4.0)版本中,有一个可以在ObjectPool<T>实现中轻松使用的ConcurrentBag类;事实上,there's an article on MSDN正是向您展示了如何做到这一点。
如果您无法访问最新的.NET框架,您可以从Microsoft's Reactive Extensions (Rx) library (在System.Threading.dll中)获得.NET 3.5中的ConcurrentBag<T>名称空间。
发布于 2009-11-09 10:24:07
CodeProject有一个示例ObjectPool实现。看一下here。或者,还有一些实现here、here和here。
https://stackoverflow.com/questions/1698738
复制相似问题