使用不同的线程更新界面(WPF) [英] Updating GUI (WPF) using a different thread

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

问题描述

只是有一个问题在这里,我不知道如何解决。我做一个小项目,涉及到一个GUI和串行数据。 GUI是由主线程运行,因为这握住我的输入串行数据中的数据变量需要不断更新,这些都是正在第二个线程更新。问题是,当我需要在图形用户界面更新一些文本框,这些都需要与数据从辅助线程更新,而这正是我的问题所在。我无法从辅助线程直接更新他们,我不知道我怎么会从我的辅助线程传输数据,并制定出从主线程更新他们的系统。我已经把我的code如下:

任何帮助将是巨大的。

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.Windows;
使用System.Windows.Controls的;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
使用System.IO;
使用System.IO.Ports;
使用的System.Threading;命名空间GUIBike
{
    ///<总结>
    ///为MainWindow.xaml交互逻辑
    ///< /总结>
    公共部分类主窗口:窗口
    {
        公共静态字符串inputdata;
        公共静态INT MaximumSpeed​​,maximumRiderInput,RiderInput,时间,CurrentSpeed​​,DistanceTravelled,MaximumMotorOutput,MotorOutput,InputSpeed​​;
        公共静态字符串SaveDataString;
        公共主题系列;
        公共静态的SerialPort SerialData;
        公共静态字符串[] = portlist SerialPort.GetPortNames();
        公共静态字符串[] =保存数据新的字符串[4];
        公共静态字符串目录=C:\\\\;        公共主窗口()
        {
            串行=新主题(READDATA);
            的InitializeComponent();
            诠释计数= 0;
            为(计数= 0; COUNT< portlist.Length;计数++)
            {
                ComPortCombo.Items.Add(portlist [计数]);
            }
        }        私人无效StartDataButton_Click(对象发件人,RoutedEventArgs E)
        {
            SerialData =新的SerialPort(ComPortCombo.Text,19200,Parity.None,8,StopBits.One);
            SerialData.Open();
            SerialData.WriteLine(P);
            Serial.Start();
            StartDataButton.IsEnabled = FALSE;
            EndDataButton.IsEnabled = TRUE;
            ComPortCombo.IsEnabled = FALSE;
            CurrentSpeed​​ = 0;
            MaximumSpeed​​ = 0;
            时间= 0;
            DistanceTravelled = 0;
            MotorOutput = 0;
            RiderInput = 0;
            保存数据[0] =;
            保存数据[1] =;
            保存数据[2] =;
            保存数据[3] =;
            SaveDataButton.IsEnabled = FALSE;
            如果(SerialData.IsOpen)
            {
                ComPortStatusLabel.Content =OPEN;
                SerialData.NewLine =/ N的;
                SerialData.WriteLine(0);
                SerialData.WriteLine(/ N);
            }
        }        私人无效EndDataButton_Click(对象发件人,RoutedEventArgs E)
        {
            SerialData.Close();
            SaveDataButton.IsEnabled = TRUE;
            SerialData.WriteLine(1);
            SerialData.WriteLine(0);
            如果(!SerialData.IsOpen)
            {
                ComPortStatusLabel.Content =封闭;
            }
            INT I = 0;
            对于(I = 0; I&下; 4;我+ +)
            {
                如果(我== 0)
                {
                    SaveDataString =MaximumSpeed​​在行驶过程中是=+ Convert.ToString(MaximumSpeed​​)+米/小时;
                    保存数据[I] = SaveDataString;
                }
                如果(ⅰ== 1)
                {
                    SaveDataString =总距离入住时间旅行=+ Convert.ToString(DistanceTravelled)+M;
                    保存数据[I] = SaveDataString;
                }
                如果(ⅰ== 2)
                {
                    SaveDataString =骑士的最大输入功率=+ Convert.ToString(maximumRiderInput)+瓦;
                    保存数据[I] = SaveDataString;
                }
                如果(我== 3)
                {
                    SaveDataString =最大电机输出功率=+ Convert.ToString(MaximumMotorOutput)+瓦;
                    保存数据[I] = SaveDataString;
                }
            }
        }        私人无效SaveDataButton_Click(对象发件人,RoutedEventArgs E)
        {
            //File.WriteAllBytes(directory +形象+ imageNO +名.txt); //将文件保存到磁盘
            File.WriteAllLines(目录+BikeData.txt,保存数据);
        }        公共无效READDATA()
        {
            INT计数器= 0;            而(SerialData.IsOpen)
            {
                如果(反== 0)
                {
                    //尝试
                    // {
                        InputSpeed​​ = Convert.ToInt16(SerialData.ReadChar());
                        CurrentSpeed​​ = InputSpeed​​;
                        如果(CurrentSpeed​​> MaximumSpeed​​)
                        {
                            MaximumSpeed​​ = CurrentSpeed​​;
                        }
                        Speed​​TextBox.Text =当前轮速=+ Convert.ToString(CurrentSpeed​​)+公里/小时;
                        DistanceTravelled = DistanceTravelled +(Convert.ToInt16(CurrentSpeed​​)*时间);
                        DistanceTravelledTextBox.Text =总距离入住时间旅行=+ Convert.ToString(DistanceTravelled)+公里;
                    //}
                    //赶上(例外){}
                }
                如果(计数器== 1)
                {
                    尝试
                    {
                        RiderInput = Convert.ToInt16(SerialData.ReadLine());
                        如果(RiderInput> maximumRiderInput)
                        {
                            maximumRiderInput = RiderInput;
                        }
                        RiderInputTextBox.Text =目前骑士输入功率=+ Convert.ToString(RiderInput)+瓦;
                    }
                    赶上(例外){}
                }
                如果(计数器== 2)
                {
                    尝试
                    {
                        MotorOutput = Convert.ToInt16(SerialData.ReadLine());
                        如果(MotorOutput> MaximumMotorOutput)
                        {
                            MaximumMotorOutput = MotorOutput;
                        }                        MotorOutputTextBox.Text =当前电机输出=+ Convert.ToString(MotorOutput)+瓦;
                    }
                    赶上(例外){}
                }
                反++;
                如果(反== 3)
                {
                    计数器= 0;
                }
            }
        }        私人无效ComPortCombo_SelectionChanged(对象发件人,SelectionChangedEventArgs E)
        {
            StartDataButton.IsEnabled = TRUE;
        }
        私人无效WINDOW_CLOSED(对象发件人,RoutedEventArgs E)
        {
            如果(SerialData.IsOpen)
            {
                SerialData.Close();
            }
        }


解决方案

您可以使用委托来解决这个问题。
这里是展示如何使用不同势线程更新一个文本框的例子

 公共委托无效UpdateTextCallback(字符串消息);私人无效TestThread()
{
    的for(int i = 0; I< = 10亿;我++)
    {
        Thread.sleep代码(1000);
        richTextBox1.Dispatcher.Invoke(
            新UpdateTextCallback(this.UpdateText)
            新的对象[] {i.ToString()}
        );
    }
}
私人无效UPDATETEXT(字符串消息)
{
    richTextBox1.AppendText(信息+\\ n);
}私人无效的button1_Click(对象发件人,RoutedEventArgs E)
{
   线程测试=新主题(新的ThreadStart(TestThread));
   test.Start();
}

TestThread方法是由线程名为test更新的textBox

Just have a problem here that I have no idea how to fix. I am doing a small project which involves a GUI and serial data. The GUI is being run by the main thread and since the data variables that hold my incoming serial data need to be updated continuously, these are being updated in a second thread. The problem is when I need to update some textboxes on the GUI, these need to be updated with data from the secondary thread and that is where my problem lies. I can't update them directly from the secondary thread and I have no idea how I would transfer data from my secondary thread and work out a system of updating them from main thread. I have put my code below:

Any help would be great.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.IO.Ports;
using System.Threading;

namespace GUIBike
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public static string inputdata;
        public static int MaximumSpeed, maximumRiderInput, RiderInput, Time, CurrentSpeed, DistanceTravelled, MaximumMotorOutput, MotorOutput, InputSpeed;
        public static string SaveDataString;
        public Thread Serial;
        public static SerialPort SerialData;
        public static string[] portlist = SerialPort.GetPortNames();
        public static string[] SaveData = new string[4];
        public static string directory = "C:\\";

        public MainWindow()
        {
            Serial = new Thread(ReadData);
            InitializeComponent();
            int Count = 0;
            for (Count = 0; Count < portlist.Length; Count++)
            {
                ComPortCombo.Items.Add(portlist[Count]);
            }
        }

        private void StartDataButton_Click(object sender, RoutedEventArgs e)
        {
            SerialData = new SerialPort(ComPortCombo.Text, 19200, Parity.None, 8, StopBits.One);
            SerialData.Open();
            SerialData.WriteLine("P");
            Serial.Start();
            StartDataButton.IsEnabled = false;
            EndDataButton.IsEnabled = true;
            ComPortCombo.IsEnabled = false;
            CurrentSpeed = 0;
            MaximumSpeed = 0;
            Time = 0;
            DistanceTravelled = 0;
            MotorOutput = 0;
            RiderInput = 0;
            SaveData[0] = "";
            SaveData[1] = "";
            SaveData[2] = "";
            SaveData[3] = "";
            SaveDataButton.IsEnabled = false;
            if (SerialData.IsOpen)
            {
                ComPortStatusLabel.Content = "OPEN";
                SerialData.NewLine = "/n";
                SerialData.WriteLine("0");
                SerialData.WriteLine("/n");
            }
        }

        private void EndDataButton_Click(object sender, RoutedEventArgs e)
        {
            SerialData.Close();
            SaveDataButton.IsEnabled = true;
            SerialData.WriteLine("1");
            SerialData.WriteLine("0");
            if (!SerialData.IsOpen)
            {
                ComPortStatusLabel.Content = "CLOSED";
            }
            int i = 0;
            for (i = 0; i < 4; i++)
            {
                if (i == 0)
                {
                    SaveDataString = "MaximumSpeed during the Ride was = " + Convert.ToString(MaximumSpeed) + "m/h";
                    SaveData[i] = SaveDataString;
                }
                if (i == 1)
                {
                    SaveDataString = "Total Distance Travelled = " + Convert.ToString(DistanceTravelled) + "m";
                    SaveData[i] = SaveDataString;
                }
                if (i == 2)
                {
                    SaveDataString = "Maximum Rider Input Power = " + Convert.ToString(maximumRiderInput) + "Watts";
                    SaveData[i] = SaveDataString;
                }
                if (i == 3)
                {
                    SaveDataString = "Maximum Motor Output Power = " + Convert.ToString(MaximumMotorOutput) + "Watts";
                    SaveData[i] = SaveDataString;
                }
            }
        }

        private void SaveDataButton_Click(object sender, RoutedEventArgs e)
        {
            //File.WriteAllBytes(directory + "image" + imageNO + ".txt", ); //saves the file to Disk    
            File.WriteAllLines(directory + "BikeData.txt", SaveData);
        }

        public void ReadData()
        {
            int counter = 0;

            while (SerialData.IsOpen)
            {
                if (counter == 0)
                {
                    //try
                    //{
                        InputSpeed = Convert.ToInt16(SerialData.ReadChar());
                        CurrentSpeed = InputSpeed;
                        if (CurrentSpeed > MaximumSpeed)
                        {
                            MaximumSpeed = CurrentSpeed;
                        }
                        SpeedTextBox.Text = "Current Wheel Speed = " + Convert.ToString(CurrentSpeed) + "Km/h";
                        DistanceTravelled = DistanceTravelled + (Convert.ToInt16(CurrentSpeed) * Time);
                        DistanceTravelledTextBox.Text = "Total Distance Travelled = " + Convert.ToString(DistanceTravelled) + "Km";
                    //}
                    //catch (Exception) { }
                }
                if (counter == 1)
                {
                    try
                    {
                        RiderInput = Convert.ToInt16(SerialData.ReadLine());
                        if (RiderInput > maximumRiderInput)
                        {
                            maximumRiderInput = RiderInput;
                        }
                        RiderInputTextBox.Text = "Current Rider Input Power =" + Convert.ToString(RiderInput) + "Watts";
                    }
                    catch (Exception) { }
                }
                if (counter == 2)
                {
                    try
                    {
                        MotorOutput = Convert.ToInt16(SerialData.ReadLine());
                        if (MotorOutput > MaximumMotorOutput)
                        {
                            MaximumMotorOutput = MotorOutput;
                        }

                        MotorOutputTextBox.Text = "Current Motor Output = " + Convert.ToString(MotorOutput) + "Watts";
                    }
                    catch (Exception) { }
                }
                counter++;
                if (counter == 3)
                {
                    counter = 0;
                }
            }
        }

        private void ComPortCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            StartDataButton.IsEnabled = true;
        }


        private void Window_Closed(object sender, RoutedEventArgs e)
        {
            if (SerialData.IsOpen)
            {
                SerialData.Close();
            }
        }

解决方案

You may use a delegate to solve this issue. Here is an example that is showing how to update a textBox using diffrent thread

public delegate void UpdateTextCallback(string message);

private void TestThread()
{
    for (int i = 0; i <= 1000000000; i++)
    {
        Thread.Sleep(1000);                
        richTextBox1.Dispatcher.Invoke(
            new UpdateTextCallback(this.UpdateText),
            new object[] { i.ToString() }
        );
    }
}
private void UpdateText(string message)
{
    richTextBox1.AppendText(message + "\n");
}

private void button1_Click(object sender, RoutedEventArgs e)
{
   Thread test = new Thread(new ThreadStart(TestThread));
   test.Start();
}

TestThread method is used by thread named test to update textBox

这篇关于使用不同的线程更新界面(WPF)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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