在 Azure IoTEdge 的模块中启动长 运行 方法的最佳方法是什么?

Whats the best way to start long running methods in modules in Azure IoTEdge?

只要设备是运行,我就需要一个保活功能运行。该方法在模块内。我发现它会在 3-10 小时后停止 运行。

// Async method to send keepalive signals
private static async void SendKeepaliveToCloudMessagesAsync()
{
    int keep_alive_counter = 0;
    while (true)
    {
        try
        {
            String timestamp = DateTimeOffset.UtcNow.ToString("u");
            String activity_type = "Device-Keepalive";
            // Create JSON message
            var telemetryDataPoint = new
            {
                timestamp,
                activity_type,
                device_id,
                keep_alive_counter
            };
            var messageString = JsonConvert.SerializeObject(telemetryDataPoint);
            var message = new Message(Encoding.ASCII.GetBytes(messageString));
            keep_alive_counter++;

            // Add a custom application property to the message.
            // An IoT hub can filter on these properties without access to the message body.
            message.Properties.Add("keepaliveAlert", (keep_alive_counter < 30) ? "true" : "false");

            // Send the telemetry message
            await s_deviceClient.SendEventAsync(message);
            Console.WriteLine("[{0}] > Sending Keepalive message: {1}", DateTimeOffset.UtcNow.ToString("u"), messageString);

            await Task.Delay(s_keepaliveInterval * 1000);
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine("Send keepalive Failed! {0}", ex);
        }
    }
}

上面的代码工作正常,持续了 3-10 个小时,但突然停止,我在 IoTHub 上没有收到保持活动消息。

我设法从日志中得到以下消息:

Send keepalive Failed! System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IoT Client'.
   at Microsoft.Azure.Devices.Client.Transport.DefaultDelegatingHandler.ThrowIfDisposed()
   at Microsoft.Azure.Devices.Client.Transport.DefaultDelegatingHandler.OpenAsync(CancellationToken cancellationToken)
   at Microsoft.Azure.Devices.Client.Transport.RetryDelegatingHandler.<>c__DisplayClass32_0.<<OpenAsyncInternal>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.Azure.Devices.Client.Transport.RetryDelegatingHandler.EnsureOpenedAsync(CancellationToken cancellationToken)
   at Microsoft.Azure.Devices.Client.Transport.RetryDelegatingHandler.<>c__DisplayClass14_0.<<SendEventAsync>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.Azure.Devices.Client.Transport.RetryDelegatingHandler.SendEventAsync(Message message, CancellationToken cancellationToken)
   at Microsoft.Azure.Devices.Client.InternalClient.SendEventAsync(Message message)
   at MotionDetection.Program.SendKeepaliveToCloudMessagesAsync() in /app/Program.cs:line 439

虽然您看到的错误不应该发生,但我仍然可以回答实际问题:

您构造模块以无限时间发送消息的方式看起来不错,通常应该可以工作。实际上,官方 repol 中 IoT Edge 团队的示例之一看起来非常像您的示例,请参见 here(对于 SendUnlimitedMessages()true 的情况)。

也许只是按照他们的例子并实现一个关闭处理程序以及一个干净的退出策略。