/// <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."); } }
/// <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()); } }