首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >库中已经有.NET的ObjectPool<T>或类似版本了吗?

库中已经有.NET的ObjectPool<T>或类似版本了吗?
EN

Stack Overflow用户
提问于 2009-11-09 09:54:37
回答 5查看 16.3K关注 0票数 14

我不想写我自己的,因为我担心我可能会遗漏一些东西和/或抄袭别人的工作,那么.NET的库中是否存在一个ObjectPool (或类似的)类?

通过对象池,我指的是帮助缓存需要很长时间才能创建的对象的类,通常用于提高性能。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-11-09 10:44:40

更新:

我也从第三方物流DataFlow提出了BufferBlock。IIRC它现在是.net的一部分。BufferBlock<T>的伟大之处在于,您可以使用PostReceiveAsync扩展方法异步等待项目变为可用。在异步/等待的世界中非常方便。

原始答案

不久前,我遇到了这个问题,并提出了一个轻量级(粗略的) threadsafe (我希望)池,它被证明非常有用,可重用和健壮:

代码语言:javascript
复制
    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();
        }
    }

为了避免池化对象的任何接口要求,对象的创建和重置都是由用户提供的委托执行的:

代码语言:javascript
复制
Pool<MemoryStream> msPool = new Pool<MemoryStream>(() => new MemoryStream(2048), pms => {
        pms.Position = 0;
        pms.SetLength(0);
    }, 500);

在池为空的情况下,BeginPop/EndPop对提供了一种异步检索对象的方法(使用Jeff Richter出色的AsyncResult实现)。

我不太记得为什么它被限制在T: class...可能什么都没有。

票数 12
EN

Stack Overflow用户

发布于 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>名称空间。

票数 18
EN

Stack Overflow用户

发布于 2009-11-09 10:24:07

CodeProject有一个示例ObjectPool实现。看一下here。或者,还有一些实现hereherehere

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1698738

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档