.NET 是否有通用对象池?

发布于 2024-08-10 03:07:50 字数 108 浏览 6 评论 0原文

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

是否有一个已经经过测试和证明的通用对象池? (我不想要 COM+ 池。)

I have a class that is expensive to construct, in terms of time and memory. I'd like to maintain a pool of these things and dispense them out on demand to multiple threads in the same process.

Is there a general-purpose object pool that is already tested and proven? (I don't want COM+ pooling.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一口甜 2024-08-17 03:07:50

下面是一个使用 .NET 4 中新的并发集合类型之一的示例,直接来自 MSDN:

以下示例演示如何使用 System.Collections.Concurrent.ConcurrentBag作为其后备存储。

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);
    }
}

Pulled straight from MSDN, here's an example of using one of the new concurrent collection types in .NET 4:

The following example demonstrates how to implement an object pool with a System.Collections.Concurrent.ConcurrentBag<T> as its backing store.

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);
    }
}
回眸一遍 2024-08-17 03:07:50

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

Microsoft.Extensions.ObjectPool NuGet 包,提供对象池 DefaultObjectPoolLeakTrackingObjectPool 的两种实现

The accepted answer is no longer correct in 2021.

There is Microsoft.Extensions.ObjectPool NuGet package, that provides two implementations of object pool DefaultObjectPool<T> and LeakTrackingObjectPool<T>

晨光如昨 2024-08-17 03:07:50

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();
}

The ObjectPool class proposed by 280Z28 looks pretty good. You might also consider creating another class that implements IDisposable and wraps the return value of GetObject(). This will ensure objects are returned to your pool and reads nicely:

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();
}
仙女山的月亮 2024-08-17 03:07:50

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

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

  1. 保留单个中央对象池。
  2. 保留一个每个线程池(缓存),该池在第一次为线程调用以及变空时填充。

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

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

如果您正确设计了类或接口,那么您可以随着时间的推移更改实现以处理更复杂的场景。

No Cheeso, there is no general object pool like this. But it is a good idea. I think this would be pretty simple to develop. The key thing is making it work well in a threaded environment.

I think this is an interesting design problem. For example, if this needs to to scale on sever class hardware -and- you will give objects to indivudual threads often then you might do this:

  1. Keep a single central pool of objects.
  2. Keep a per-thread pool (a cache) that is populated when its called for the first time for a thread, and when it becomes empty.

This way, you avoid per-thread contention for most requests.

Different operational conditions would lead you to a different design. For example, if object allocations are rare or the number of threads is low, then it might be simpler just to have a lock around a collection. This won't scale well, but in this case, it would need to.

If you design the class or interface correctly, then you could change the implementation over time to handle more complex scenarios.

猥︴琐丶欲为 2024-08-17 03:07:50

为什么不只编写一个单例来充当已创建的对象数组的网关。

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

通过使用单例,您可以为所有要调用的内容提供一个静态类,如果昂贵的类是单例的内部类,那么没有其他方法可以创建昂贵的类,并且您可以轻松控制要创建的对象数量。

Why not just write a singleton that just serves as the gateway to the array of objects that has been created.

When an object is handed out, then remove it from the available list, put it in the checked out list, and then when it is returned, reverse that.

By using a singleton for this you have a static class for everything to call, and if the expensive class is an inner class of the singleton, then nothing else can create the expensive class, and you can control how many objects to create, easily.

岁月流歌 2024-08-17 03:07:50

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

Just to share. I created a generic .net common pool library using Apache Common pool as a model. http://cobrary.wordpress.com/net-common-pool-library/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文