【发布时间】:2021-10-07 16:53:26
【问题描述】:
使用 Microsoft.Azure.Devices.Client.DeviceClient .net 框架 4.8 时,关闭应用程序会使多个线程运行。特别是 DotNetty.Common.dll! DotNetty.Common.Concurrency.SingleThreadEventExecutor.PollTask
Microsoft.Azure.Devices 的 1.34.0 和 1.35.0 版本存在同样的问题。 我们使用 DeviceClient 是否不当? 这是我不理解的异步事情吗? 我错过了正确关闭它的电话吗?
从网上的例子来看,我不应该做任何特别的事情,它应该自己关闭。 但是它仍然挂起,目前这是一个紧密的实现。我还没有独立制作,所以我没有重复这个问题,只运行 DeviceClient 代码
当程序退出时,is_running 被设置,程序关闭其他线程。最终我们调用 Environment.Exit(0);
这应该是所有相关的代码
private void thread_method()
{
using (var _deviceClient = DeviceClient.CreateFromConnectionString(connection), TransportType.Mqtt))
{
while (is_running)
{
var db = new Database(); // roughly an open entity framework connection
List <class> unprocessed_messages = db.GetUnprocessed();
List<List<Messages>> processed = breakup_method(unprocessed_messages);
foreach (var sublist in processed)
{
if (!await SendMessages(sublist , _deviceClient))
break;
// the processed sublist was successful
db.SaveChanges(); // make sure we dont send again
}
}
Thread.Sleep(500);
await _deviceClient.CloseAsync();
}
}
private async Task<bool> SendMessages(List<Message> messages, DeviceClient _deviceClient)
{
try
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(5000);
CancellationToken cancellationToken = cancellationTokenSource.Token;
await _deviceClient.SendEventBatchAsync(messages, cancellationToken);
if (cancellationToken.IsCancellationRequested)
return false;
return true;
}
catch (Exception e)
{
// logging
}
return false;
}
不同的方法,它不会主动发送任何东西。 只是一个打开,睡眠直到程序退出,然后关闭, 全部在 using 语句中。 8 个线程仍在运行 PollTask,并且在设置上述所有内容所花费的时间中,是我等待它们关闭的时间。这至少是 5 分钟。
private void thread_method()
{
using (var _deviceClient = DeviceClient.CreateFromConnectionString(connection), TransportType.Mqtt))
{
await _deviceClient.OpenAsync();
while (is_running) Thread.Sleep(500);
await _deviceClient.CloseAsync();
}
}
最后一次更新,独立的控制台应用程序。 100% 不是我的问题。
// Repost just in case
class Program
{
private static string _connection_string = $"HostName={url};DeviceId={the_id};SharedAccesskey={key}";// fill your in
public static bool is_running = false;
static void Main(string[] args)
{
is_running = true;
new System.Threading.Thread(new System.Threading.ThreadStart(thread_method)).Start();
Console.WriteLine("enter to exit");
String line = Console.ReadLine();
is_running = false;
}
public static async void thread_method()
{
using (var _deviceClient = DeviceClient.CreateFromConnectionString(_connection_string, TransportType.Mqtt))
{
await _deviceClient.OpenAsync();
while (is_running) System.Threading.Thread.Sleep(500);
await _deviceClient.CloseAsync();
}
}
}
https://github.com/Azure/azure-sdk-for-net/issues/24550 撞到合适的位置 https://github.com/Azure/azure-iot-sdk-csharp/issues/2194
【问题讨论】: