Che*_*eso 19 .net c# object-pooling
在时间和记忆方面,我有一个构建成本昂贵的类.我想维护这些东西的池,并在同一过程中根据需要将它们分配给多个线程.
是否存在已经过测试和验证的通用对象池?(我不想要COM +汇集.)
Sam*_*ell 23
直接从MSDN拉出,这是一个使用.NET 4中新的并发集合类型之一的示例:
以下示例演示如何使用a
System.Collections.Concurrent.ConcurrentBag<T>作为其后备存储来实现对象池.
public class ObjectPool<T>
{
private ConcurrentBag<T> _objects;
private Func<T> _objectGenerator;
public ObjectPool(Func<T> objectGenerator)
{
if (objectGenerator == null)
throw new ArgumentNullException("objectGenerator");
_objects = new ConcurrentBag<T>();
_objectGenerator = objectGenerator;
}
public T GetObject()
{
T item;
if (_objects.TryTake(out item))
return item;
return _objectGenerator();
}
public void PutObject(T item)
{
_objects.Add(item);
}
}
Run Code Online (Sandbox Code Playgroud)
280Z28提出的ObjectPool类看起来很不错.您还可以考虑创建另一个实现IDisposable的类并包装GetObject()的返回值.这将确保将对象返回到您的池并且可以很好地读取:
class ObjectPoolReference<T> : IDisposable
{
public ObjectPool<T> Pool { get; private set; }
public T Instance { get; private set; }
public ObjectPoolReference(ObjectPool<T> pool, T instance)
{
Pool = pool;
Instance = instance;
}
~ObjectPoolReference()
{
Dispose();
}
#region IDisposable Members
private bool _Disposed = false;
public void Dispose()
{
if (!_Disposed)
{
Pool.PutObject(Instance);
_Disposed = true;
}
}
#endregion
}
//instance of the pool
ObjectPool<Foo> Pool;
//"using" ensures the reference is disposed at the end of the block, releasing the object back to the pool
using (var Ref = Pool.GetObject())
{
Ref.Instance.DoSomething();
}
Run Code Online (Sandbox Code Playgroud)
没有Cheeso,没有像这样的通用对象池.但这是个好主意.我认为开发起来非常简单.关键是让它在线程环境中运行良好.
我认为这是一个有趣的设计问题.例如,如果这需要在服务器类硬件上进行扩展 - 并且您将经常为单个线程提供对象,那么您可以这样做:
这样,您可以避免大多数请求的每线程争用.
不同的操作条件会导致您采用不同的设计.例如,如果对象分配很少或者线程数很少,那么只是锁定集合可能更简单.这不会很好地扩展,但在这种情况下,它需要.
如果正确设计类或接口,则可以随时更改实现以处理更复杂的方案.
2021 年,接受的答案不再正确。
有Microsoft.Extensions.ObjectPoolDefaultObjectPool<T> NuGet 包,它提供了对象池和对象池的两种实现LeakTrackingObjectPool<T>