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

时间:2009-11-04 04:49:07

标签: c# .net object-pooling

在时间和记忆方面,我有一个构建成本昂贵的类。我想维护这些东西的池,并在同一过程中根据需要将它们分配给多个线程。

是否有经过测试和验证的通用对象池? (我不想要COM +汇集。)

6 个答案:

答案 0 :(得分:22)

直接从MSDN中获取,这是在.NET 4中使用其中一种新的并发集合类型的示例:

  

以下示例演示如何实现一个以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);
    }
}

答案 1 :(得分: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();
}

答案 2 :(得分:5)

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

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

  1. 保留一个中央对象池。
  2. 保留一个每线程池(一个缓存),当它第一次为一个线程调用时,以及当它变为空时填充。
  3. 这样,您可以避免大多数请求的每线程争用。

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

    如果您正确设计了类或接口,那么您可以随时更改实现以处理更复杂的方案。

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

为什么不编写一个仅用作已创建对象数组的网关的单例。

分发对象时,将其从可用列表中删除,将其放入签出列表中,然后在返回时将其反转。

通过使用单例,你有一个静态类可以调用所有东西,如果昂贵的类是单例的内部类,那么没有别的东西可以创建昂贵的类,你可以控制创建的对象数量,很容易。

答案 5 :(得分:0)

分享。我使用Apache Common pool作为模型创建了一个通用的.net公共池库。 http://cobrary.wordpress.com/net-common-pool-library/