/// <summary>
        /// the helper function to perform the retriable operations.
        /// </summary>
        /// <param name="retriableOperation">the delegation method.</param>
        /// <param name="format">the error format string when exception raised.</param>
        /// <param name="objParams">the params for the format string.</param>
        public static void PerformRetriableOperation(RetriableOperation retriableOperation, string format, params object[] objParams)
        {
            int retryNumber = 0;

            do
            {
                try
                {
                    retriableOperation(retryNumber);
                    return;
                }
                catch (MessageQueueException e)
                {
                    // the msmq queue cannot access, then retry 3 times.
                    if (MessageQueueHelper.CanRetry(e))
                    {
                        retryNumber++;
                        if (retryNumber < MessageQueueHelper.RetryCount)
                        {
                            string errorMessage = string.Empty;
                            if (!string.IsNullOrEmpty(format))
                            {
                                errorMessage = string.Format(CultureInfo.InvariantCulture, format, objParams) + ", and";
                            }

                            errorMessage += "Will perform retry[" + retryNumber.ToString(CultureInfo.InvariantCulture) + "], the exception:" + e.ToString();
                            BrokerTracing.TraceWarning(errorMessage);
                        }
                        else
                        {
                            throw MessageQueueHelper.ConvertMessageQueueException(e);
                        }
                    }
                    else
                    {
                        throw MessageQueueHelper.ConvertMessageQueueException(e);
                    }
                }
                catch (Exception)
                {
                    throw;
                }

                System.Threading.Thread.Sleep(100);
            }while (retryNumber > 0);
        }
        /// <summary>
        /// Callback function invoked on BeginPeek completion.
        /// </summary>
        /// <param name="ar"></param>
        private void PeekMessageComplete(IAsyncResult ar)
        {
            BrokerTracing.TraceVerbose("[MSMQMessageFetcher] .PeekMessageComplete: Peek message complete.");

            Exception exception = null;

            System.Messaging.Message message         = null;
            bool             needRetry               = false;
            RefCountedCursor storedMessagePeekCursor = ar.AsyncState as RefCountedCursor;

            this.rwlockMessagePeekCursorField.EnterReadLock();
            try
            {
                try
                {
                    //
                    // Check if target queue is disposed. If so, don't call EndPeek.  However, the check doesn't guarantee
                    // that msmqQueueField is valid when EndPeek is invoked on it. So ObjectDisposedException shall be handled.
                    //
                    if (this.isQueueDisposed)
                    {
                        BrokerTracing.TraceWarning("[MSMQMessageFetcher]) .PeekMessageComplete: target queue is disposed");
                        return;
                    }

                    message = this.msmqQueueField.EndPeek(ar);
                    Interlocked.Increment(ref this.peekCursorPosition);
                }
                catch (MessageQueueException e)
                {
                    if (this.isDisposedField)
                    {
                        this.RevertFetchCount();
                        return;
                    }

                    needRetry = MessageQueueHelper.HandleAsyncCallbackError(
                        e,
                        ref this.messagePeekActionField,
                        "[MSMQMessageFetcher] .PeekMessageComplete: EndPeek message failed, outstandingPeekCount:{0}, messageCount={1}",
                        this.outstandingFetchCount,
                        this.msmqMessageCount);

                    if (!needRetry)
                    {
                        BrokerTracing.TraceError(
                            "[MSMQMessageFetcher] .PeekMessageComplete: end peek message failed, outstandingPeekCount:{0}, messageCount:{1} Exception:{2}",
                            this.outstandingFetchCount,
                            this.msmqMessageCount,
                            e);
                        exception = e;
                    }
                }
                catch (Exception e)
                {
                    if (this.isDisposedField)
                    {
                        this.RevertFetchCount();
                        return;
                    }

                    BrokerTracing.TraceError("[MSMQMessageFetcher] .PeekMessageComplete: end peek message failed, Exception:{0}", e.ToString());
                    exception = e;
                }
                finally
                {
                    storedMessagePeekCursor.Release();
                }
            }
            finally
            {
                this.rwlockMessagePeekCursorField.ExitReadLock();
            }

            if (needRetry)
            {
                Interlocked.Increment(ref this.pendingFetchCount);
                return;
            }

            if (message == null && exception == null)
            {
                BrokerTracing.TraceWarning("[MSMQMessageFetcher] .PeekMessageComplete: EndPeek return null.");
            }

            if (message != null)
            {
                // if the message is one of the partial messages
                if (message.AppSpecific > 0 && !string.IsNullOrEmpty(message.Label))
                {
                    try
                    {
                        BrokerTracing.TraceVerbose(
                            "[MSMQMessageFetcher] .PeekMessageComplete: peek partial message with AppSpecific {0} and Label {1}.", message.AppSpecific, message.Label);
                        string[] labels    = message.Label.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
                        string   groupId   = labels[0];
                        int      msgNumber = int.Parse(labels[1]);
                        ConcurrentDictionary <int, Message> messages = this.partialMessages.GetOrAdd(groupId, (k) => new ConcurrentDictionary <int, Message>());
                        if (!messages.TryAdd(msgNumber, message))
                        {
                            BrokerTracing.TraceError(
                                "[MSMQMessageFetcher] .PeekMessageComplete: try add one of the composed messages failed. Message Label {0}.", message.Label);
                        }

                        // check if all partial messages are peeked and cached
                        if (this.partialMessageCounters.AddOrUpdate(groupId, 1, (k, v) => v + 1) == message.AppSpecific)
                        {
                            BrokerTracing.TraceVerbose(
                                "[MSMQMessageFetcher] .PeekMessageComplete: all partial messages are peeked and cached for group {0}.", groupId);
                            Message msg = new Message();
                            msg.BodyType = message.BodyType;
                            byte[]      buffer    = new byte[Constant.MSMQChunkSize];
                            List <long> lookUpIds = new List <long>(message.AppSpecific);
                            for (int i = 1; i <= message.AppSpecific; i++)
                            {
                                Message m     = messages[i];
                                int     count = m.BodyStream.Read(buffer, 0, Constant.MSMQChunkSize);
                                msg.BodyStream.Write(buffer, 0, count);
                                lookUpIds.Add(m.LookupId);
                            }
                            msg.BodyStream.Position = 0;
                            BrokerQueueItem brokerQueueItem = null;

                            // Deserialize message to BrokerQueueItem
                            try
                            {
                                brokerQueueItem = (BrokerQueueItem)this.messageFormatter.Read(msg);
                                brokerQueueItem.PersistAsyncToken.AsyncToken = lookUpIds.ToArray();
                            }
                            catch (Exception e)
                            {
                                BrokerTracing.TraceError(
                                    "[MSMQMessageFetcher] .PeekMessageComplete: deserialize message failed for composed messages with groupId {0}, Exception:{1}", groupId,
                                    e);
                                exception = e;
                            }

                            messages.Clear();
                            if (!this.partialMessages.TryRemove(groupId, out messages))
                            {
                                BrokerTracing.TraceWarning(
                                    "[MSMQMessageFetcher] .PeekMessageComplete: try to remove partial messages with groupId {0} from cahce failed.", groupId);
                            }
                            int messageCount;
                            if (!this.partialMessageCounters.TryRemove(groupId, out messageCount))
                            {
                                BrokerTracing.TraceWarning(
                                    "[MSMQMessageFetcher] .PeekMessageComplete: try to remove partial message counters with groupId {0} from cahce failed.", groupId);
                            }

                            this.HandleMessageResult(new MessageResult(brokerQueueItem, exception));
                        }
                        else
                        {
                            Interlocked.Increment(ref this.pendingFetchCount);
                        }
                    }
                    catch (Exception ex)
                    {
                        BrokerTracing.TraceError(
                            "[MSMQMessageFetcher] .PeekMessageComplete: peek composed message failed, Exception:{0}", ex);
                    }
                }
                else
                {
                    BrokerQueueItem brokerQueueItem = null;

                    // Deserialize message to BrokerQueueItem
                    try
                    {
                        brokerQueueItem = (BrokerQueueItem)this.messageFormatter.Read(message);
                        brokerQueueItem.PersistAsyncToken.AsyncToken = new long[1] {
                            message.LookupId
                        };
                    }
                    catch (Exception e)
                    {
                        BrokerTracing.TraceError(
                            "[MSMQMessageFetcher] .PeekMessageComplete: deserialize message failed, Exception:{0}",
                            e.ToString());
                        exception = e;
                    }

                    this.HandleMessageResult(new MessageResult(brokerQueueItem, exception));
                }
            }
        }