是否有.NET的通用对象池?

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)


Mic*_*ito 6

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)


For*_*ker 5

没有Cheeso,没有像这样的通用对象池.但这是个好主意.我认为开发起来非常简单.关键是让它在线程环境中运行良好.

我认为这是一个有趣的设计问题.例如,如果这需要在服务器类硬件上进行扩展 - 并且您将经常为单个线程提供对象,那么您可以这样做:

  1. 保留一个中心对象池.
  2. 保留一个每线程池(一个缓存),当它第一次为一个线程调用时,以及当它变为空时填充.

这样,您可以避免大多数请求的每线程争用.

不同的操作条件会导致您采用不同的设计.例如,如果对象分配很少或者线程数很少,那么只是锁定集合可能更简单.这不会很好地扩展,但在这种情况下,它需要.

如果正确设计类或接口,则可以随时更改实现以处理更复杂的方案.


Luk*_*brt 5

2021 年,接受的答案不再正确。

Microsoft.Extensions.ObjectPoolDefaultObjectPool<T> NuGet 包,它提供了对象池和对象池的两种实现LeakTrackingObjectPool<T>