从新线程更新winform [英] Update winform from a new thread

查看:37
本文介绍了从新线程更新winform的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从GPS / IMU组合中收集实时数据,并在WinForm标签中连续显示信息。我将在主程序中获取GPS / IMU数据,然后启动一个线程以实时显示数据,同时主程序继续收集数据。我能够在一个简短的测试用例中完成这项工作但是当我扩展测试以将线程代码放在一个单独的类中时,我遇到了问题。首先是代码,然后我将介绍这些问题:



数据放在类的属性中 - 类代码为:



I am trying to collect real time data from an GPS/IMU combination and display the information continuously in a WinForm Label. I will be getting the GPS/IMU data in the main program and then starting a thread to display the data in real time while the main program continues to collect the data. I was able to make this work in a short test case but when I expanded the test to put the thread code in a separate class I am having problems. First the code and then I'll cover the issues:

Data is placed in properties in a class-the class code for this is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Thread_Test_Sending_Data_to_Thread_Function
{
    public class FormData
    {
        public int Label1Data;
        public int Label2Data;
    }
}





收集数据并启动当前仅使用set的线程的主程序数据是:





The main program to collect the data and start the thread which is currently only using set data is:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;


namespace Thread_Test_Sending_Data_to_Thread_Function
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            int i;
            InitializeComponent();
            FormData FormData1 = new FormData();
            Thread1 MyThread = new Thread1();


            for (i = 1; i < 5; i++)
            {
                FormData1.Label1Data = i;
                FormData1.Label2Data = i * 10;
                Thread WriteScreen = new Thread(delegate ()
                {
                    MyThread.FormWriteMethod(FormData1, TestLabel1);
                });

                WriteScreen.Start();
                Thread.Sleep(1000);
            }
        }



   }

}





线程类的代码是:



The code for the thread class is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using System.Windows.Forms;





namespace Thread_Test_Sending_Data_to_Thread_Function
{

    public class Thread1
    {
        int testInt1;
        int testInt2;
        int test;
        private delegate void SetLabelTextDelegate(FormData InputClass);
        public void FormWriteMethod(FormData InputClass, Label lbl)
        {
            testInt1 = InputClass.Label1Data;
            testInt2 = InputClass.Label2Data;
 
            UpdateLabel(lbl, InputClass.Label1Data.ToString());
        }
        void UpdateLabel(Label lbl, string text)

        {
            if (lbl.InvokeRequired)

            {
                lbl.Invoke(new Action<Label, string>(UpdateLabel), new object[] { lbl, text });
            }

            else
            {
                lbl.Text = text;
            }
            
        }
    }





基于在VS中使用调试器我很确定线程正在启​​动,因为线程中的代码运行。当我第一次尝试这样做时,我没有传递WinForm标签的标签,并且尝试使用InvokeRequired方法导致InvokeRequired不在上下文中。我添加了将标签传递给线程,然后lbl.InvokeRequired编译。但是,它总是表示false并且lbl.Text = text;加载标签但标签内容在主程序退出之前不会显示。这意味着即使在启动新线程之后,线程仍然在控制GUI的主线程中。几天来一直在努力,没有任何积极的结果。非常感谢任何帮助。



我的尝试:



我尝试将InvokeRequired代码移动到FormWriteMethod,以查看是否以某种方式调用第二个方法以某种方式退出显示线程并返回主线程,但这似乎没有帮助。



Based on using the debugger in VS I am pretty sure the thread is being properly initiated in that the code in the thread runs. When I first started trying to do this I didn't pass the label for the WinForm Label the thread and trying the InvokeRequired method resulted in a InvokeRequired not in context. I added passing the label to the thread and then lbl.InvokeRequired compiled. However, it always indicates false and the lbl.Text=text; loads the label but the label contents are not displayed until the main program exits. This implies that even after starting the new thread that the thread is still in the main thread that controls the GUI. Have been working on this for days with no positive results. Would appreciate any help.

What I have tried:

I tried moving the InvokeRequired code to the FormWriteMethod to see if somehow calling a second method somehow got out of the display thread and back to the main thread but that didn't seem to help.

推荐答案

这出错的原因是你的主线程执行循环,并在每次迭代时进入等待状态( Sleep )。当主线程正在运行(包括处于等待状态)时,它无法处理消息。你需要将 for 循环放到另一个线程中,或者,哪个更好,完全摆脱它,并将代码放在 for 循环,减去 Sleep ,进入计时器事件。



表单本身需要发送消息才能进行更新。
Where this is going wrong is that your main thread performing the loop, and going into a wait state (Sleep) on each iteration. While the main thread is running (including in the wait state), it is not able to process messages. You need to either put the for loop into another thread, or, which would be better, get rid of it altogether, and put the code inside of the for loop, minus the Sleep, into a timer event.

The form itself need to be pumping its messages for the updates to occur.


这篇关于从新线程更新winform的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆