private void QueueWaitingCheckTask()
        {
            //ensure queues are processed if queue count is < _maxfetchcount after a time elasped of no messages incoming (waiting)
            Task.Run(async() =>
            {
                while (true)
                {
                    try
                    {
                        if (DateTime.UtcNow.Subtract(LastMessageTime).TotalSeconds > 5)
                        {
                            try
                            {
                                await semaphoreSlim.WaitAsync();

                                var processingCollection = ClientMessages.Take((int)MaxFetchCount).ToDictionary(k => k.Key, v => v.Value);

                                if (!(Model?.IsClosed).GetValueOrDefault())
                                {
                                    BasicGetResult messageResult = null;


                                    try { messageResult = Model?.BasicGet(QueueName, false); }
                                    catch (Exception ex)
                                    {
                                        Debug.WriteLine(ex.ToString(), "QueueWaitingCheckTask => BasicGet");
                                        queueWaitErrorAction?.Invoke(ex);
                                    }

                                    //flush the queue until we reach max or null
                                    while (messageResult != null & processingCollection.Count < (int)MaxFetchCount)
                                    {
                                        var message = BasicPropertiesHelper.DecodeMessage <TMessage>(messageResult.BasicProperties, messageResult.Body);
                                        if (!processingCollection.ContainsKey(messageResult.DeliveryTag))
                                        {
                                            processingCollection.Add(messageResult.DeliveryTag, ProcessingMessage.Add(messageResult.DeliveryTag, message));
                                        }

                                        messageResult = Model?.BasicGet(QueueName, false);
                                    }
                                }

                                if (processingCollection?.Count > 0)
                                {
                                    if (!Model.IsClosed)
                                    {
                                        //both of these should not be implemented one or the other

                                        //if single message handler is created
                                        var processedMessage = processingCollection.Values.Select(v => (TMessage)v.Message).FirstOrDefault();
                                        if (processedMessage != null)
                                        {
                                            if (messageFunctionAsync != null)
                                            {
                                                await messageFunctionAsync?.Invoke(processedMessage);
                                            }

                                            if (messageFunction != null)
                                            {
                                                messageFunction?.Invoke(processedMessage);
                                            }
                                        }

                                        if (processingCollection?.Values != null)
                                        {
                                            var messages = processingCollection.Values?.Where(v => v.Message != null).Select(v => (TMessage)v.Message);
                                            //if multi messagehandler is created
                                            if (multipleMessagesFunctionAsync != null)
                                            {
                                                await multipleMessagesFunctionAsync?.Invoke(messages);
                                            }

                                            if (multipleMessagesFunction != null)
                                            {
                                                multipleMessagesFunction?.Invoke(messages);
                                            }
                                        }
                                    }
                                    //ack the messages
                                    foreach (var processing in processingCollection)
                                    {
                                        //remove processed message
                                        if (!Model.IsClosed)
                                        {
                                            ClientMessages.Remove(processing.Key);
                                            Model.BasicAck(processing.Key, false);
                                        }
                                    }
                                }
                            }
                            finally
                            {
                                LastMessageTime = DateTime.UtcNow;
                                semaphoreSlim.Release();
                            }
                        }
                        await Task.Delay(100);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.ToString(), "QueueWaitingCheckTask");
                        queueWaitErrorAction?.Invoke(ex);
                    }
                } //while
            }).ConfigureAwait(false); //Task.Run
        }
        /// <summary>
        /// Called each time a message arrives for this consumer.
        /// </summary>
        /// <remarks>
        /// </remarks>
        public override void HandleBasicDeliver(
            string consumerTag,
            ulong deliveryTag,
            bool redelivered,
            string exchange,
            string routingKey,
            IBasicProperties properties,
            byte[] body)
        {
            TMessage message = default;

            Task.Run(async() =>
            {
                try
                {
                    if ((Model?.IsClosed).GetValueOrDefault())
                    {
                        return;
                    }

                    message = BasicPropertiesHelper.DecodeMessage <TMessage>(properties, body);
                    if (message == null)
                    {
                        //wrong message shouldn't be in this queue so remove it without requeue
                        //not in the ClientMessages collection yet

                        Model.BasicReject(deliveryTag, false);
                    }

                    //process the messages once we hit the fetch count
                    try
                    {
                        await semaphoreSlim.WaitAsync();

                        if (MaxFetchCount > 1)
                        {
                            //add a message to process

                            ClientMessages.Add(deliveryTag, ProcessingMessage.Add(deliveryTag, message));

                            if (ClientMessages.Count == MaxFetchCount)
                            {
                                var processingCollection = ClientMessages.Take((int)MaxFetchCount).ToDictionary(k => k.Key, v => v.Value);

                                var toProcessMessages = processingCollection?.Where(v => v.Value.Message != null)?.Select(v => (TMessage)v.Value.Message);
                                //execute work action
                                if (multipleMessagesFunctionAsync != null)
                                {
                                    await multipleMessagesFunctionAsync?.Invoke(toProcessMessages);
                                }

                                if (multipleMessagesFunction != null)
                                {
                                    multipleMessagesFunction?.Invoke(toProcessMessages);
                                }

                                foreach (var processing in processingCollection)
                                {
                                    if (!Model.IsClosed)
                                    {
                                        ClientMessages.Remove(processing.Key);

                                        //ack the message
                                        Model.BasicAck(processing.Key, false);
                                    }
                                }
                            }

                            if (ClientMessages.Count > MaxFetchCount)
                            {
                                if (!Model.IsClosed)
                                {
                                    ClientMessages.Remove(deliveryTag);

                                    //reject and requeue message we are at max fetch count
                                    Model.BasicReject(deliveryTag, true);
                                }
                            }
                        }
                        else //process messages one at a time
                        {
                            if (!Model.IsClosed)
                            {
                                //if maxfetch is <= 1 then process and ack a single message

                                if (messageFunctionAsync != null)
                                {
                                    await messageFunctionAsync?.Invoke(message);
                                }

                                if (messageFunction != null)
                                {
                                    messageFunction?.Invoke(message);
                                }

                                if (multipleMessagesFunctionAsync != null)
                                {
                                    await multipleMessagesFunctionAsync?.Invoke(new TMessage[] { message });
                                }

                                if (multipleMessagesFunction != null)
                                {
                                    multipleMessagesFunction?.Invoke(new TMessage[] { message });
                                }

                                ClientMessages.Remove(deliveryTag);
                                Model.BasicAck(deliveryTag, false);
                            }
                        }
                    }
                    finally
                    {
                        LastMessageTime = DateTime.UtcNow;
                        semaphoreSlim.Release();
                    }
                }
                catch (Exception ex)
                {
                    //Model.BasicNack(deliveryTag, false, false);
                    Debug.WriteLine(ex.ToString(), "HandleBasicDeliver");
                    errorAction?.Invoke(ex, message);
                }
            });
        }