Reputation: 733
We get this weird error after running our Azure worker role (Event Processor Host) for some time. Initially I thought it was due to us queueing too many cloud to device messages via ServiceClient (Microsoft.Azure.Devices) but surely we will see a "Device Queue depth cannot exceed 50 messages" ERROR. We are also very careful about closing and disposing as well.
Code below:
public async Task<AzureDevices.Message> SendCloudToDeviceAsync(string deviceId, string message, bool ack = false, string MessageId = null)
{
AzureDevices.ServiceClient ServiceClient = null;
try
{
ServiceClient = AzureDevices.ServiceClient.CreateFromConnectionString(Configuration.IOTHubConnectionString);
await ServiceClient.OpenAsync();
logger.Info(string.Format("Encoding & Sending message {0} for Device {1}", message, deviceId));
var commandMessage = new AzureDevices.Message(Encoding.ASCII.GetBytes(message))
{
//Whether we require feedback from the hub...
Ack = ack == true ? AzureDevices.DeliveryAcknowledgement.Full : AzureDevices.DeliveryAcknowledgement.None,
MessageId = MessageId == null ? Guid.NewGuid().ToString() : MessageId,
//ExpiryTimeUtc = expiry,
To = deviceId
};
await ServiceClient.SendAsync(deviceId, commandMessage);
Common.ExtensionMethods.WriteHighlightedMessage(string.Format("Sent message {0} with MessageId {1}", message, commandMessage.MessageId), ConsoleColor.Green);
logger.Info(string.Format("Sent message {0} with MessageId {1}", message, commandMessage.MessageId));
return commandMessage;
}
catch (Exception e)
{
Common.ExtensionMethods.WriteHighlightedMessage(string.Format("SendCloudToDeviceMessageAsync: {0}", e.Message), ConsoleColor.Red);
if (e.Message.Contains("Device Queue depth cannot exceed 50 messages"))
{
logger.Warn("SendCloudToDeviceMessageAsync for device {0}: {1}", deviceId, e.Message);
if (e.InnerException != null) logger.Warn(e.InnerException);
}
else
{
logger.Error("SendCloudToDeviceMessageAsync for device {0}: {1}", deviceId, e.Message);
logger.Error(e.StackTrace);
if (e.InnerException != null) logger.Error(e.InnerException);
}
}
finally
{
if(ServiceClient != null)
{
await ServiceClient.CloseAsync();
ServiceClient.Dispose();
}
}
return new AzureDevices.Message();
}
Here is part of the InnerException: System.IO.IOException: The encryption operation failed, see inner exception. ---> System.ComponentModel.Win32Exception: The context has expired and can no longer be used
The Exact line the error is triggered is on OpenAsync(). I very well may doing this on multiple threads, is there a limit?
In a future release, we wont be doing an "application layer ACK" but rather let the decide think the server is happy via an MQTT ACK. This will drop the amount of cloud to device messages we are sending.
Upvotes: 2
Views: 1328
Reputation: 4432
Device-To-Cloud commands are queued on IoT Hub and delivered asynchronously only when the device is connected. Only 50 commands can be queued per device.Please see here.Even though you have closed the service client,the command is still in the queue in service-end until the device client receive the messages completely.So i think you should make sure that the command in the queue is not over the limitation.
Upvotes: 1