ServiceClient(Microsoft.Azure.Devices)OpenAsync问题

时间:2018-04-20 09:06:59

标签: c# azure mqtt amqp azure-iot-hub

运行我们的Azure辅助工具角色(事件处理器主机)一段时间后,我们遇到了这个奇怪的错误。最初我认为这是由于我们通过ServiceClient(Microsoft.Azure.Devices)排队太多云到设备的消息,但我们肯定会看到一个"设备队列深度不能超过50条消息"错误。我们对关闭和处理也非常谨慎。

以下代码:

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

以下是InnerException的一部分: System.IO.IOException:加密操作失败,请参阅内部异常。 ---&GT; System.ComponentModel.Win32Exception:上下文已过期且无法再使用

触发错误的Exact行是在OpenAsync()上。 我很可能在多个线程上执行此操作,是否有限制?

在将来的版本中,我们不会做一个&#34;应用程序层ACK&#34;而是让决定通过MQTT ACK认为服务器是满意的。这会将云量减少到我们发送的设备消息。

1 个答案:

答案 0 :(得分:1)

Device-To-Cloud命令在IoT Hub上排队,仅在连接设备时异步传送。每个设备只能排队50个命令。请参阅here。即使您关闭了服务客户端,该命令仍然在服务端的队列中,直到设备客户端完全收到消息。所以我认为你应该确保队列中的命令没有超出限制。