更改 WindowsForms UI 在一个 Task 中 c#

huangapple go评论105阅读模式
英文:

Changing WindowsForms UI in a Task c#

问题

I wrote a windows forms application where I receive messages with MQTTNet from the broker. I want to change the UI according to the received message. But I couldn't make it happen. I took the client code from the MQTTNet github page. When I receive the message, I want to change a label. Because it is a task, I had to call the invoke function, but it never executes. The function to change the label is called, but the change statement is never reached.

public Form1()
{
    InitializeComponent();
    trainCount = 1;
    tagCount = 2;
    trains = new Train[trainCount];
    tags = new Tag[tagCount];
    InitializeTrains();
    InitializeTags();
    control = this;
    Task task = Handle_Received_Application_Message();
}
public async Task Handle_Received_Application_Message()
{
    var mqttFactory = new MqttFactory();

    using (var mqttClient = mqttFactory.CreateMqttClient())
    {
        var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1").Build();

        mqttClient.ApplicationMessageReceivedAsync += async e =>
        {
            Console.WriteLine("Received application message.");
            Console.WriteLine(e.ApplicationMessage.ConvertPayloadToString());
            for (int i = 0; i < tagCount; i++)
            {
                if (tags[i].code.CompareTo(e.ApplicationMessage.ConvertPayloadToString()) == 0)
                {
                    for (int k = 0; k < trainCount; k++)
                    {
                        if (e.ApplicationMessage.ConvertPayloadToString().Substring(0, 2).CompareTo(trains[k].code) == 0)
                        {
                            Console.WriteLine("In Tag Event");
                            trains[k].currentTag = tags[i];
                            var message = e.ApplicationMessage.ConvertPayloadToString();
                            await ChangeUI(); // Change UI is called here.
                        }
                    }
                }
            }
        };

        await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);

        var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
            .WithTopicFilter(
                f =>
                {
                    f.WithTopic("anten/main");
                })
            .Build();

        await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);

        Console.WriteLine("MQTT client subscribed to topic.");
        Console.ReadKey();
    }
}
public async Task ChangeUI()
{
    if (InvokeRequired)
        BeginInvoke(new MethodInvoker(
            delegate
            {
                ChangeUI().Wait();
            }
        ));
    else
    {
        label1.Text = "sadasdasd";  // Code never reaches here.
    }
}

I tried creating a different thread when a message is received, but it didn't work neither.

Any help would be appreciated. I got stuck on this for 10 hours.

英文:

I wrote a windows forms application where I receive messages with MQTTNet from the broker. I want to change the UI according to the received message. But I couldn't make it happen. I took the client code from the MQTTNet github page. When I receive the message, I want to change a label. Because it is a task, I had to call the invoke function, but it never executes. The function to change the label is called, but the change statement is never reached.

public Form1()
        {
            InitializeComponent();
            trainCount = 1;
            tagCount = 2;
            trains = new Train[trainCount];
            tags = new Tag[tagCount];
            InitializeTrains();
            InitializeTags();
            control = this;
            Task task = Handle_Received_Application_Message();
        }
public async Task Handle_Received_Application_Message()
        {

            var mqttFactory = new MqttFactory();

            using (var mqttClient = mqttFactory.CreateMqttClient())
            {
                var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer(&quot;127.0.0.1&quot;).Build();

                mqttClient.ApplicationMessageReceivedAsync += e =&gt;
                {
                    Console.WriteLine(&quot;Received application message.&quot;);
                    Console.WriteLine(e.ApplicationMessage.ConvertPayloadToString());
                    for (int i = 0; i &lt; tagCount; i++)
                    {
                        if (tags[i].code.CompareTo(e.ApplicationMessage.ConvertPayloadToString()) == 0)
                        {
                            for (int k = 0; k &lt; trainCount; k++)
                            {
                                if (e.ApplicationMessage.ConvertPayloadToString().Substring(0, 2).CompareTo(trains[k].code) == 0)
                                {
                                    Console.WriteLine(&quot;In Tag Event&quot;);

                                    trains[k].currentTag = tags[i];
                                    var message = e.ApplicationMessage.ConvertPayloadToString();
                                    ChangeUI(); //Change UI is called here.
                                    
                                }
                            }
                        }
                    }
                    
                    return Task.CompletedTask;
                };

                await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);

                var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
                    .WithTopicFilter(
                        f =&gt;
                        {
                            f.WithTopic(&quot;anten/main&quot;);
                        })
                    .Build();

                await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);

                Console.WriteLine(&quot;MQTT client subscribed to topic.&quot;);
                Console.ReadKey();
            }


        }
public void ChangeUI()
        {
            if (InvokeRequired)
                BeginInvoke(new MethodInvoker(
                    delegate
                    {
                ChangeUI();
                    }
                    ));
            else
            {
                label1.Text = &quot;sadasdasd&quot;;  // Code never reaches here.
            }
        }

I tried creating a different thread when a message is received, but it didn't work neither.

Any help would be appreciated. I got stuck on this for 10 hours.

答案1

得分: 2

Console.ReadKey 会阻止 Windows 消息循环执行,从而阻止任何 UI 更新。

我建议移除 Console.ReadKey,并且还要移除 Handle_Received_Application_Message 中的 using,以便不销毁客户端。而是在 Handle_Received_Application_Message 中创建一个成员变量来持有客户端,在应用程序开始关闭时进行销毁。

英文:

Console.ReadKey will prevent the Windows message loop from executing, which prevents any UI updates.

I recommend removing Console.ReadKey and also removing the using in Handle_Received_Application_Message so the client is not disposed. Instead of disposing the client in Handle_Received_Application_Message, create a member variable to hold the client and dispose it when your application begins to shut down.

huangapple
  • 本文由 发表于 2023年3月7日 21:32:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75662639.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定