首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HostedService阻塞UI线程?

HostedService阻塞UI线程?
EN

Stack Overflow用户
提问于 2022-05-16 11:08:34
回答 2查看 189关注 0票数 0

我在后台任务中有MQTT订阅服务器的以下代码:

代码语言:javascript
复制
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using PickByLight.BackgroundTask.Models;
using PickByLight.Database.Wrapper.Interfaces;
using PickByLight.Logic;
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;

namespace PickByLight.BackgroundTask
{
    /// <summary>
    /// Hosted MQTT Background Service
    /// </summary>
    public class HostedMQTTService : IHostedService, IDisposable
    {


        private readonly Task _executingTask;
        private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource();
        /// <summary>
        /// MQTT Client
        /// </summary>
        private MqttClient MqttClient { get; set; }

        /// <summary>
        /// Name of the Pick by Light
        /// </summary>
        private string PickByLight_Name { get; set; }

        /// <summary>
        /// MQTT is activated
        /// </summary>
        private bool MqttIsActive { get; set; }

        /// <summary>
        /// IP Adress of the MQTT URL
        /// </summary>
        private string MqttURL { get; set; }


        /// <summary>
        /// Storage Process for an material
        /// </summary>
        private MaterialStorageProcess StorageProcess { get; set; }

        /// <summary>
        /// Service Scope Factory
        /// </summary>
        private IServiceScopeFactory ServiceScopeFactory { get; set; }

        /// <summary>
        /// Configuration
        /// </summary>
        private IConfiguration Configuration { get; set; }

        /// <summary>
        /// Logger
        /// </summary>
        private readonly ILogger<HostedMQTTService> _logger;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="configuration"></param>
        public HostedMQTTService(IConfiguration configuration, ILogger<HostedMQTTService> logger, IServiceScopeFactory serviceScopeFactory)
        {
            this.PickByLight_Name = configuration.GetValue<string>("PickByLight_Name");
            this.MqttURL = configuration.GetValue<string>("MQTTUrl");
            this.MqttIsActive = configuration.GetValue<bool>("MQTTConnection");
            this.ServiceScopeFactory = serviceScopeFactory;
            this.Configuration = configuration;
            this._logger = logger;
        }

        /// <summary>
        /// Start the Task of the Background Service
        /// </summary>
        public Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Background-Service started...");
            while (true)
            {
                try
                {
                    //No Object is created
                    if (this.MqttClient == null)
                    {
                        _logger.LogInformation("Try to establishe new MQTT Client");
                        this.MqttClient = CreateNewMqttConnection();
                    }
                    else if (this.MqttClient.IsConnected == false)
                    {
                        _logger.LogInformation("MQTT Client is disconnected... Try to reconnect!");
                        this.MqttClient = CreateNewMqttConnection();
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Ein schwerwiegender Fehler im MQTT Background-Service ist aufgetreten.");
                }
            }
        }

        /// <summary>
        /// Prints out all received messages
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Mqtt_Message_Received(object sender, MqttMsgPublishEventArgs e)
        {
            try
            {
                var agcMessage = Encoding.UTF8.GetString(e.Message);
                _logger.LogInformation("Topic: " + e.Topic + " | Nachricht: " + agcMessage + " | QOS: " + e.QosLevel);

                var resultString = Encoding.UTF8.GetString(e.Message);
                MqttReadTopicClass mqttContent = JsonConvert.DeserializeObject<MqttReadTopicClass>(resultString);

                using (var scope = this.ServiceScopeFactory.CreateScope())
                {
                    var storageConfigurationManager = scope.ServiceProvider.GetService<IStorageConfigurationManager>();
                    var storageElementManager = scope.ServiceProvider.GetService<IStorageElementManager>();
                    this.StorageProcess = new MaterialStorageProcess(storageConfigurationManager, storageElementManager, this.Configuration);


                    StorageProcess.Remove(mqttContent.storageLocation);
                }

            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Schwerwiegender Fehler beim Lesen von MQTT Nachrichten");
            }
        }




        /// <summary>
        /// Create new MQTT connection if connection is lost or doesn't exist
        /// </summary>
        private MqttClient CreateNewMqttConnection()
        {
            _logger.LogInformation("Create MQTT Client");
            MqttClient client = new MqttClient(this.MqttURL, 32005, false, null, null, MqttSslProtocols.None);
            string clientId = Guid.NewGuid().ToString();
            client.MqttMsgPublishReceived += Mqtt_Message_Received;
            client.Connect(clientId);
            client.Subscribe(new string[] { "buttonpress_sepioo_pdi/" + this.PickByLight_Name }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
            _logger.LogInformation("MQTT Client created");
            return client;
        }

        /// <summary>
        /// Stop the Task of the Background Service
        /// </summary>
        public async Task StopAsync(CancellationToken cancellationToken)
        {
            //Stop called without start
            if (_executingTask == null)
            {
                return;
            }

            try
            {
                //Signal cancellation to the executing method
                _stoppingCts.Cancel();
            }
            finally
            {
                //wait until the task completes or the stop token triggers
                await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, cancellationToken));
            }
        }

        /// <summary>
        /// Dispose the Background Service
        /// </summary>
        public void Dispose()
        {
            _stoppingCts.Cancel();
        }

    }
}

在我的startup.cs文件中,我执行以下操作:

代码语言:javascript
复制
//Register Background Task
services.AddHostedService<HostedMQTTService>();

问题是,在我看来,托管服务阻塞了用户界面/webserver线程,因为我无法访问.net 6 mvc应用程序的url。

你能给我一个提示或解决这个问题的方法吗?

谢谢。

EN

回答 2

Stack Overflow用户

发布于 2022-05-16 12:35:30

您需要将您的StartAsync-method更改为如下所示:

代码语言:javascript
复制
   public Task StartAsync(CancellationToken cancellationToken)
    {
        return Task.Run(() => 
        {
            _logger.LogInformation("Background-Service started...");

            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    //No Object is created
                    if (this.MqttClient == null)
                    {
                        _logger.LogInformation("Try to establish new MQTT Client");
                        this.MqttClient = CreateNewMqttConnection();
                    }
                    else if (this.MqttClient.IsConnected == false)
                    {
                        _logger.LogInformation("MQTT Client is disconnected... Try to reconnect!");
                        this.MqttClient = CreateNewMqttConnection();
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Ein schwerwiegender Fehler im MQTT Background-Service ist aufgetreten.");
                }
            }
        });
    }
票数 1
EN

Stack Overflow用户

发布于 2022-05-16 11:22:59

您正在阻止该进程,因为您的托管服务从未启动。

  1. 从Start方法中删除while(true)循环。
  2. 确保base.StartAsync(cancellationToken);总是被调用。

编辑:我看到您实现了IHostedService接口。尝试从BackgroundService类继承

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72258240

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档