-1

c# で特定のオブジェクト プールを作成しようとしています。getObject と putObject の 2 つの基本的なメソッドと、1 つのスレッドセーフなコレクション (concurrentDictionary) があります (プール内のオブジェクトを識別するためのキーが必要なため)。

しかし、辞書からオブジェクトを削除して返すときは、このコレクションを再編成する必要があり、新しいオブジェクトをコレクションに入れたいときは、キーを自動インクリメントしたいと考えています。これを達成するための解決策はありますか? または、同じ効果を達成するのに役立ち、オブジェクトプールの作成に役立つ他のコレクションはありますか? (オブジェクトを作成するための 2 つのプールがありますが、オブジェクトにはデータを含めることができるため、「データ プール」もいくつかあり、「データ」は一定でないサイズのオブジェクトである必要があります。「データ プール」にはこのソリューションが必要です) .

または、サイズの異なるさまざまなデータを含めることができるオブジェクトでオブジェクトプール(メモリプール)を作成する方法について、いくつかのノウハウがありますか?

いくつかのサンプルコード

->「データオブジェクト」のサイズの最も近い一致を見つけたいので、Foreachがあります。適切なオブジェクトがあれば、それを返したいです。無ければ新規作成します。

namespace MPool
{
    public class DataPool<T>
    {
        private ConcurrentDictionary<int,T> _objects;
        private Func<T> _objectGenerator;

        public DataPool(Func<T> objectGenerator)
        {
            if (objectGenerator == null)
                throw new ArgumentNullException("Chyba metoda objectGenerator");
            _objects = new ConcurrentDictionary<int,T>();
            _objectGenerator = objectGenerator;
        }

        public T GetObject(int size)
        {
            int diverse = Int32.MaxValue;
            T item = default(T);
            int key = -1;
            foreach (KeyValuePair<int,T> obj in _objects) {
                if (GetObjectSize(obj.Value) == size) {
                    //item = obj.Value;
                    key = obj.Key;
                    break;
                } else {
                    if (Math.Abs((GetObjectSize(obj.Value) - size)) < diverse) {
                        diverse = Math.Abs((GetObjectSize(obj.Value) - size));
                        if (diverse < (2 * GetObjectSize(obj.Value))) {
                            //item = obj.Value;
                            key = obj.Key;
                        }
                    }
                }
            }
            if (key==-1) {
                return _objectGenerator();
            } else {
                _objects.TryRemove(key, out item);
                return item;
            }
        }

        public void PutObject(T item)
        {
            //_objects.AddOrUpdate
        }

        public void Free()
        {
            while (!_objects.IsEmpty) {
                _objects.Clear();
            }
        }

        private int GetObjectSize(T TestObject)
        {
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            byte[] Array;
            bf.Serialize(ms, TestObject);
            Array = ms.ToArray();
            return Array.Length;
        }
    }
}
4

1 に答える 1

0

投稿されたコードについて、あなたがやろうとしていることとは直接関係のないコメントがありますが (あなたが何をしたいのかまだよくわからないため)、これは対処する必要があると思います。

オブジェクトのサイズを、各ループ反復で潜在的に 4 回計算しています。一度にこれらのオブジェクトをコレクションに追加するので、オブジェクトとそのサイズを格納できるヘルパー クラスをこのクラス内に作成し、作成時にそれを計算してから、これらのオブジェクトをコレクションに格納することをお勧めします。

public DataPool<T>
{
        internal class DataStructHelper<T>
        {
            public T DataObject { get; private set; }
            public int Size { get; private set; }
            public DataStructHelper(T dataObject)
            {
                DataObject = dataObject;
                Size = GetObjectSize(dataObject);
            }

            private int GetObjectSize(T TestObject)
            {
                BinaryFormatter bf = new BinaryFormatter();
                using (MemoryStream ms = new MemoryStream())
                {
                    byte[] Array;
                    bf.Serialize(ms, TestObject);
                    return ms.ToArray().Length;
                }
            }
        }
    }
// Other code here
}

クラスがどのように使用されるか、これをヒットする予定のスレッドの数などがわからない場合は、通常のリストを使用してアクセスをロックすることを検討します。アイテムを並べ替えた順序で保存し、BinarySearch を使用してサイズに基づいてアイテムを挿入および検索できます (比較機能を提供する必要があります)。

于 2012-11-05T21:32:02.180 に答える