/// <summary>
        /// the out T can be null and return will be false
        /// if the queue is empty, then this function will be blocked until new message arrive
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool TryDequeue(out T msg)
        {
            if (IsQueueEmpty)
            {
                WaitForMsgEvent.Wait(cts.Token);
                WaitForMsgEvent.Reset();
            }

            bool ret = false;

            if (!bWritingQueueA)
            {
                ret = QueueA.TryDequeue(out msg);
            }
            else
            {
                ret = QueueB.TryDequeue(out msg);
            }

            if (!ret && ((!bWritingQueueA && QueueA.Count == 0) || (bWritingQueueA && QueueB.Count == 0)))
            {
                if (bWritingQueueA)
                {
                    bWritingQueueA = false;
                }
                else
                {
                    bWritingQueueA = true;
                }
            }

            return(ret);
        }
        public void Enqueue(T obj)
        {
            if (bWritingQueueA)
            {
                QueueA.Enqueue(obj);
            }
            else
            {
                QueueB.Enqueue(obj);
            }

            if (WaitForMsgEvent.SpinCount > 0)
            {
                WaitForMsgEvent.Set();
            }
        }