Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating GUI (WPF) using a different thread

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();             }         } 
like image 506
user517002 Avatar asked Nov 23 '10 05:11

user517002


People also ask

Is WPF multi threaded?

WPF supports a single-threaded apartment model that has the following rules: One thread runs in the entire application and owns all the WPF objects. WPF elements have thread affinity, in other words other threads can't interact with each other.

What is UI thread in WPF?

The UI thread queues work items inside an object called a Dispatcher. The Dispatcher selects work items on a priority basis and runs each one to completion. Every UI thread must have at least one Dispatcher, and each Dispatcher can execute work items in exactly one thread.

What is dispatcher thread in WPF?

A dispatcher is often used to invoke calls on another thread. An example would be if you have a background thread working, and you need to update the UI thread, you would need a dispatcher to do it. Follow this answer to receive notifications.

What is thread affinity in WPF?

WPF requires that most of its objects be tied to the UI thread. This is known as thread affinity, meaning you can only use a WPF object on the thread on which it was created.


1 Answers

You can use Dispatcher.Invoke to update your GUI from a secondary thread.

Here is an example:

    private void Window_Loaded(object sender, RoutedEventArgs e)     {         new Thread(DoSomething).Start();     }     public void DoSomething()     {         for (int i = 0; i < 100000000; i++)         {                this.Dispatcher.Invoke(()=>{                textbox.Text=i.ToString();                });             }      } 
like image 182
Slaven Tojic Avatar answered Sep 22 '22 15:09

Slaven Tojic