C# ServiceClient(Microsoft.Azure.Devices)OpenAsync问题

C# ServiceClient(Microsoft.Azure.Devices)OpenAsync问题,c#,azure,mqtt,amqp,azure-iot-hub,C#,Azure,Mqtt,Amqp,Azure Iot Hub,在运行Azure worker角色(事件处理器主机)一段时间后,我们出现了这个奇怪的错误。起初我认为这是因为我们通过ServiceClient(Microsoft.Azure.Devices)将太多的云到设备消息排队,但我们肯定会看到“设备队列深度不能超过50条消息”错误。我们对关闭和处置也非常谨慎 下面的代码: public async Task<AzureDevices.Message> SendCloudToDeviceAsync(string deviceId, string

在运行Azure worker角色(事件处理器主机)一段时间后,我们出现了这个奇怪的错误。起初我认为这是因为我们通过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();
}
公共异步任务SendCloudToDeviceAsync(字符串设备ID,字符串消息,bool ack=false,字符串消息ID=null)
{
AzureDevices.ServiceClient ServiceClient=null;
尝试
{                
ServiceClient=AzureDevices.ServiceClient.CreateFromConnectionString(Configuration.IoTubConnectionString);
等待ServiceClient.OpenAsync();
Info(string.Format(“为设备{1}编码和发送消息{0}”,消息,设备ID));
var commandMessage=new AzureDevices.Message(Encoding.ASCII.GetBytes(Message))
{
//我们是否需要中心的反馈。。。
Ack=Ack==true?AzureDevices.DeliveryAcknowledge.Full:AzureDevices.DeliveryAcowledge.None,
MessageId=MessageId==null?Guid.NewGuid().ToString():MessageId,
//ExpiryTimeUtc=到期,
To=设备ID
};
等待ServiceClient.SendAsync(deviceId,commandMessage);
Common.ExtensionMethods.WriteHighlightedMessage(string.Format(“发送消息{0},消息ID为{1}”)、message、commandMessage.MessageId)、ConsoleColor.Green);
Info(string.Format(“发送消息{0},消息ID为{1}”,消息,commandMessage.MessageId));
返回命令消息;
}
捕获(例外e)
{
Common.ExtensionMethods.WriteHighlightedMessage(string.Format(“sendcloudToDeviceMessageSync:{0}”,e.Message),ConsoleColor.Red);
if(例如,Message.Contains(“设备队列深度不能超过50条消息”))
{
logger.Warn(“设备{0}:{1}的SendCloudToDeviceMessageAsync”,设备ID,e.Message);
如果(e.InnerException!=null)logger.Warn(e.InnerException);
}
其他的
{
logger.Error(“设备{0}:{1}的SendCloudToDeviceMessageAsync”,设备ID,e.Message);
记录器错误(例如StackTrace);
如果(e.InnerException!=null)logger.Error(e.InnerException);
}
}
最后
{
if(ServiceClient!=null)
{
等待ServiceClient.CloseAsync();
ServiceClient.Dispose();
}
}
返回新的AzureDevices.Message();
}
这里是InnerException的一部分: System.IO.IOException:加密操作失败,请参阅内部异常。-->System.ComponentModel.Win32Exception:上下文已过期,无法再使用

触发错误的确切行位于OpenAsync()上。 我很可能在多个线程上执行此操作,有限制吗


在未来的版本中,我们不会执行“应用程序层ACK”,而是让决策者通过MQTT ACK认为服务器是满意的。这将减少我们发送的云到设备消息的数量。

设备到云命令在IoT Hub上排队,并且仅在设备连接时异步传递。每个设备只能排队50条命令。请参阅。即使您关闭了服务客户端,该命令仍在服务端的队列中,直到设备客户端完全接收到消息。因此,我认为您应该确保队列中的命令未超过限制。

嘿,谢谢您的评论。我觉得这不是唯一的原因,因为当这种情况发生时,我们会得到一个不同的错误。然而,一切皆有可能。顺便说一句,如果是这样的话,我很高兴,但我更喜欢一致的错误。更新:我们刚刚确认,这只是发生在我们的生产实例的一个设备,有0 C2D计数。我不能复制的问题。你能分享更多关于多线程的代码吗?嘿,很抱歉反应太晚了,我们以为这个错误消失了,但它一直存在,现在只是经常发生。我们的S1集线器有6台。当然,我们创建的线程数量与我们正在处理的理论无关?“请求已被限制。请等待10秒,然后重试。操作类型:C2DSend跟踪Id:9ff36ad6e8e040f39281b23e2477bd5f-G:11时间戳:07/18/2018 12:14:07”。如果有帮助的话?这是对云到设备发送的数量的限制吗?我很确定我们没有使用每分钟600(100*6个单位)。我们也经常“无法连接”。这有关系吗?