我不想编写自己的书,因为恐怕我可能会错过某些东西和/或剥夺他人的工作,那么.NET库中是否存在ObjectPool(或类似的)类?

对于对象池,我的意思是一个类,该类有助于缓存需要很长时间才能创建的对象,通常用于提高性能。

最佳答案

更新:

我还要从TPL DataFlow提出 BufferBlock<T> 。 IIRC现在是.net的一部分。 BufferBlock<T>的伟大之处在于,您可以使用 Post<T> ReceiveAsync<T> 扩展方法异步等待项变得可用。在异步/等待世界中非常方便。

原始答案

前一段时间,我遇到了这个问题,并提出了一个轻量级(准备就绪)线程安全(我希望)池,该池已被证明非常有用,可重用且健壮:

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

为了避免池对象的任何接口(interface)要求,对象的创建和重置均由用户提供的委托(delegate)执行:
Pool<MemoryStream> msPool = new Pool<MemoryStream>(() => new MemoryStream(2048), pms => {
        pms.Position = 0;
        pms.SetLength(0);
    }, 500);

在池为空的情况下,BeginPop / EndPop对提供了一种APM(ish)手段,当一个对象可用时(使用Jeff Richter出色的AsyncResult<TResult>实现)异步检索对象。

我不太记得为什么它只限于T:class ...可能没有。

关于c# - 库中已经存在ObjectPool <T>或类似的.NET?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1698738/

10-15 09:48