//private static void ReconfigLazyInstance()
        //{

        //    _instance = new Lazy<SocketAsyncEventArgsPool>(
        //        PoolFactory,
        //        false);
        //}


        public static SocketAsyncEventArgsPool GetInstance()
        {
            //lock (_criticalLock)
            //{
            //    return _instance.Value;
            //}
            if (_instance == null)
            {
                lock (_criticalLock)
                {
                    if (_instance == null)
                    {
                        _instance = PoolFactory();
                    }
                }
            }
            return(_instance);
        }
 //private static void ReconfigLazyInstance()
 //{
 //    _instance = new Lazy<SocketAsyncEventArgsPool>(
 //        PoolFactory,
 //        false);
 //}
 public static SocketAsyncEventArgsPool GetInstance()
 {
     //lock (_criticalLock)
     //{
     //    return _instance.Value;
     //}
     if (_instance == null)
     {
         lock (_criticalLock)
         {
             if (_instance == null)
             {
                 _instance = PoolFactory();
             }
         }
     }
     return _instance;
 }
        private static SocketAsyncEventArgsPool PoolFactory()
        {
            //Create buffer blocks.
            //long acturalBufferSize = (long)_poolSize * (long)_bufferSize;
            //var steps = acturalBufferSize / _bufferBlockStepSize;
            //var mod = acturalBufferSize % _bufferBlockStepSize;
            //if (mod > 0)
            //{
            //    steps++;
            //}
            //int maxBufferBlockSize = _maxBuffersInBufferBlockCount * _bufferSize;
            //long totalSize = (long)(steps * _bufferBlockStepSize);
            //var fullBlockCount = (int)(totalSize / maxBufferBlockSize);
            //var lastBlockSize = totalSize % maxBufferBlockSize;
            //var buffers =
            //    Enumerable.Range(0, fullBlockCount)
            //        .Select(
            //            i => new byte[maxBufferBlockSize]
            //            )
            //        .ToList();
            //if (lastBlockSize != 0) buffers.Add(new byte[(int)lastBlockSize]);

            //Create reserved items in overlap pool.
            //These overlap objects in SAES will be return to overlap pool for other io after SAE pool is built.

            var reservedList = Enumerable.Range(0, _reservedOverlapCount)
                .Select(
                    i =>
                    {
                        unsafe
                        {
                            NativeOverlapped* ptr = new Overlapped().Pack((x, y, z) => { }, null);
                            return new Action(() =>
                            {
                                Overlapped.Free(ptr);
                            });
                        }

                    }
                )
                .ToList();

            //Create working SAEs
            var query = Enumerable.Range(0, _poolSize)
                .Select
                (
                    i =>
                    {
                        var e = new SocketAsyncEventArgs();
                        //long totalOffset = i * (long)_bufferSize;
                        //var blockIndex = (int)(totalOffset / maxBufferBlockSize);
                        //var offset = (int)(totalOffset % maxBufferBlockSize);
                        e.SetBuffer(new byte[_bufferSize], 0, _bufferSize);
                        return e;
                    }
                );
            var itmsList = query.ToList();

            //Create SAE pool instance
            var rval = new SocketAsyncEventArgsPool(new ConcurrentBag<SocketAsyncEventArgs>(itmsList));

            //Release the reserved overlap object.
            //Best practice of overlap pool: the last released object will be visited first.

            reservedList.Reverse();
            reservedList.ForEach(
                act =>
                {
                    try
                    {
                        act();
                    }
                    catch (Exception)
                    {
                    }

                }
                );
            reservedList.Clear();

            //make sure all items in pool are in MaxGen of GC
            for (int i = 0; i < GC.MaxGeneration; i++)
            {

                GC.Collect();
                GC.WaitForFullGCComplete();

            }
            //Pin all buffer & SocketEventArgs to GC.
            //GC will ignore them.

            return rval;
        }
        private static SocketAsyncEventArgsPool PoolFactory()
        {
            //Create buffer blocks.
            //long acturalBufferSize = (long)_poolSize * (long)_bufferSize;
            //var steps = acturalBufferSize / _bufferBlockStepSize;
            //var mod = acturalBufferSize % _bufferBlockStepSize;
            //if (mod > 0)
            //{
            //    steps++;
            //}
            //int maxBufferBlockSize = _maxBuffersInBufferBlockCount * _bufferSize;
            //long totalSize = (long)(steps * _bufferBlockStepSize);
            //var fullBlockCount = (int)(totalSize / maxBufferBlockSize);
            //var lastBlockSize = totalSize % maxBufferBlockSize;
            //var buffers =
            //    Enumerable.Range(0, fullBlockCount)
            //        .Select(
            //            i => new byte[maxBufferBlockSize]
            //            )
            //        .ToList();
            //if (lastBlockSize != 0) buffers.Add(new byte[(int)lastBlockSize]);

            //Create reserved items in overlap pool.
            //These overlap objects in SAES will be return to overlap pool for other io after SAE pool is built.


            var reservedList = Enumerable.Range(0, _reservedOverlapCount)
                               .Select(
                i =>
            {
                unsafe
                {
                    NativeOverlapped *ptr = new Overlapped().Pack((x, y, z) => { }, null);
                    return(new Action(() =>
                    {
                        Overlapped.Free(ptr);
                    }));
                }
            }
                )
                               .ToList();

            //Create working SAEs
            var query = Enumerable.Range(0, _poolSize)
                        .Select
                        (
                i =>
            {
                var e = new SocketAsyncEventArgs();
                //long totalOffset = i * (long)_bufferSize;
                //var blockIndex = (int)(totalOffset / maxBufferBlockSize);
                //var offset = (int)(totalOffset % maxBufferBlockSize);
                e.SetBuffer(new byte[_bufferSize], 0, _bufferSize);
                return(e);
            }
                        );
            var itmsList = query.ToList();

            //Create SAE pool instance
            var rval = new SocketAsyncEventArgsPool(new ConcurrentBag <SocketAsyncEventArgs>(itmsList));


            //Release the reserved overlap object.
            //Best practice of overlap pool: the last released object will be visited first.

            reservedList.Reverse();
            reservedList.ForEach(
                act =>
            {
                try
                {
                    act();
                }
                catch (Exception)
                {
                }
            }
                );
            reservedList.Clear();

            //make sure all items in pool are in MaxGen of GC
            for (int i = 0; i < GC.MaxGeneration; i++)
            {
                GC.Collect();
                GC.WaitForFullGCComplete();
            }
            //Pin all buffer & SocketEventArgs to GC.
            //GC will ignore them.


            return(rval);
        }