简体   繁体   English

HostedService 阻塞 UI 线程?

[英]HostedService blocks UI Thread?

I have the following code for a MQTT Subscriber in a Background Task:我在后台任务中有以下 MQTT 订阅者代码:

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

    }
}

In my startup.cs File i am doing the following:在我的 startup.cs 文件中,我正在执行以下操作:

//Register Background Task
services.AddHostedService<HostedMQTTService>();

The problem is, that it seems to me that the hosted service is blocking the user-interface/webserver threads because i can not access the url of the .net 6 mvc application.问题是,在我看来,托管服务正在阻止用户界面/网络服务器线程,因为我无法访问 .net 6 mvc 应用程序的 url。

Could you give me a hint or a solution to this problem?你能给我一个提示或解决这个问题的方法吗?

Thanks.谢谢。

You are blocking the process, because your hosted service never starts.您正在阻止该过程,因为您的托管服务永远不会启动。

  1. Remove the while(true) loop from the Start method.从 Start 方法中删除while(true)循环。
  2. Ensure base.StartAsync(cancellationToken);确保base.StartAsync(cancellationToken); is always called.总是被调用。

Edit : I saw you implement the IHostedService interface.编辑:我看到你实现了 IHostedService 接口。 Try to inherits from the BackgroundService class尝试从 BackgroundService 类继承

You will need to change your StartAsync -method to something like this:您需要将您的StartAsync -方法更改为以下内容:

   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.");
                }
            }
        });
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM