/// <summary>
        /// Dequeue messages
        /// </summary>
        private async Task DeQueueMessagesAsync(CancellationToken ct)
        {
            try
            {
                if (_defaultSendIntervalSeconds > 0 && _maxSizeOfIoTHubMessageBytes > 0)
                {
                    // send every x seconds
                    Trace($"Start timer to send data to IoTHub in {_defaultSendIntervalSeconds} seconds.");
                    _sendTimer = new Timer(async state => await SendToIoTHubAsync(), null, TimeSpan.FromSeconds(_defaultSendIntervalSeconds), TimeSpan.FromSeconds(_defaultSendIntervalSeconds));
                }

                WaitHandle[] waitHandles = { _sendQueueEvent, ct.WaitHandle };
                while (true)
                {
                    // wait till some work needs to be done
                    WaitHandle.WaitAny(waitHandles);

                    // do we need to stop
                    if (ct.IsCancellationRequested)
                    {
                        Trace($"Cancellation requested. Sending {_sendQueue.Count} remaining messages.");
                        await SendToIoTHubAsync();

                        break;
                    }

                    if (_sendQueue.Count > 0)
                    {
                        bool   isPeekSuccessful     = false;
                        bool   isDequeueSuccessful  = false;
                        string messageInJson        = string.Empty;
                        int    nextMessageSizeBytes = 0;

                        // perform a TryPeek to determine size of next message
                        // and whether it will fit. If so, dequeue message and add it to the list.
                        // if it cannot fit, send current message to IoTHub, reset it, and repeat.

                        isPeekSuccessful = _sendQueue.TryPeek(out messageInJson);

                        // get size of next message in the queue
                        if (isPeekSuccessful)
                        {
                            nextMessageSizeBytes = Encoding.UTF8.GetByteCount(messageInJson);

                            // sanity check that the user has set a large enough IoTHub messages size.
                            if (nextMessageSizeBytes > _maxSizeOfIoTHubMessageBytes && _maxSizeOfIoTHubMessageBytes > 0)
                            {
                                Trace(Utils.TraceMasks.Error, $"There is a telemetry message (size: {nextMessageSizeBytes}), which will not fit into an IoTHub message (max size: {_maxSizeOfIoTHubMessageBytes}].");
                                Trace(Utils.TraceMasks.Error, $"Please check your IoTHub message size settings. The telemetry message will be discarded silently. Sorry:(");
                                _sendQueue.TryDequeue(out messageInJson);
                                continue;
                            }
                        }

                        // determine if it will fit into remaining space of the IoTHub message or if we do not batch at all
                        // if so, dequeue it
                        if (_currentSizeOfIotHubMessageBytes + nextMessageSizeBytes < _maxSizeOfIoTHubMessageBytes || _maxSizeOfIoTHubMessageBytes == 0)
                        {
                            isDequeueSuccessful = _sendQueue.TryDequeue(out messageInJson);

                            // add dequeued message to list
                            if (isDequeueSuccessful)
                            {
                                OpcUaMessage msgPayload = JsonConvert.DeserializeObject <OpcUaMessage>(messageInJson);
                                _messageListSemaphore.Wait();
                                _messageList.Add(msgPayload);
                                _messageListSemaphore.Release();
                                _currentSizeOfIotHubMessageBytes = _currentSizeOfIotHubMessageBytes + nextMessageSizeBytes;
                                Trace(Utils.TraceMasks.OperationDetail, $"Added new message with size {nextMessageSizeBytes} to IoTHub message (size is now {_currentSizeOfIotHubMessageBytes}). {_sendQueue.Count} message(s) in send queue.");

                                // fall through, if we should send immediately
                                if (_maxSizeOfIoTHubMessageBytes != 0)
                                {
                                    continue;
                                }
                            }
                        }

                        // the message needs to be sent now.
                        Trace(Utils.TraceMasks.OperationDetail, $"IoTHub message complete. Trigger send of message with size {_currentSizeOfIotHubMessageBytes} to IoTHub.");
                        await SendToIoTHubAsync();
                    }
                }
            }
            catch (Exception e)
            {
                Trace(e, "Error while dequeuing messages.");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Dequeue messages
        /// </summary>
        private static async Task DeQueueMessagesAsync(CancellationToken ct)
        {
            try
            {
                //Send every x seconds, regardless if IoT Hub message is full.
                Timer sendTimer = new Timer(async state => await SendToIoTHubAsync(), null, 0, m_defaultSendIntervalInMilliSeconds);

                while (true)
                {
                    if (ct.IsCancellationRequested)
                    {
                        Trace("Cancellation requested. Sending remaining messages.");
                        sendTimer.Dispose();
                        await SendToIoTHubAsync();

                        break;
                    }


                    if (m_sendQueue.Count > 0)
                    {
                        bool   isPeekSuccessful     = false;
                        bool   isDequeueSuccessful  = false;
                        string messageInJson        = string.Empty;
                        int    nextMessageSizeBytes = 0;

                        //Perform a TryPeek to determine size of next message
                        //and whether it will fit. If so, dequeue message and add it to the list.
                        //If it cannot fit, send current message to IoT Hub, reset it, and repeat.

                        isPeekSuccessful = m_sendQueue.TryPeek(out messageInJson);

                        //Get size of next message in the queue
                        if (isPeekSuccessful)
                        {
                            nextMessageSizeBytes = System.Text.Encoding.UTF8.GetByteCount(messageInJson);
                        }

                        //Determine if it will fit into remaining space of the IoT Hub message.
                        //If so, dequeue it
                        if (m_currentSizeOfIoTHubMessageBytes + nextMessageSizeBytes < m_maxSizeOfIoTHubMessageBytes)
                        {
                            isDequeueSuccessful = m_sendQueue.TryDequeue(out messageInJson);

                            //Add dequeued message to list
                            if (isDequeueSuccessful)
                            {
                                OpcUaMessage msgPayload = JsonConvert.DeserializeObject <OpcUaMessage>(messageInJson);

                                m_messageList.Add(msgPayload);

                                m_currentSizeOfIoTHubMessageBytes = m_currentSizeOfIoTHubMessageBytes + nextMessageSizeBytes;
                            }
                        }
                        else
                        {
                            //Message is full. Send it to IoT Hub
                            await SendToIoTHubAsync();
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine("Error dequeuing message: " + exception.ToString());
            }
        }