I have a WPF which executes a GUI for serial communication. I want to keep triggering the device and recoed the values till the user says stop. I have a global bool variable STOP which I set to false when user presses the stop which in turn should terminate the while loop which triggers the device continuously but the problem is that once the user selects the run button whcih runs the while loop, the WPF app freezes and doesn’t accept the STOP button click.
Can someone give me an idea of what is happening here or a any suggestion on how to implement it differently.
Here is my code
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.Ports;
using Keyence.data_class;
using Microsoft.Win32;
using System.IO;
using Keyence;
using System.Threading;
namespace Keyence
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public static string filePath;
public static string fileName;
public static int baudrate = 9600;
public static string thresHold = "60";
public bool STOP = true;
public static char[] buffer = new char[256];
public static string x, y, match;
public static string value;
public static SerialPort port = new SerialPort("COM4", baudrate, Parity.None, 8, StopBits.One);
public MainWindow()
{
InitializeComponent();
//port.DataReceived
//SerialPort port = new SerialPort(COM, baudrate, Parity.None, 8, StopBits.One);
port.Open();
port.NewLine = "\r";
//*******display camera types*****
string[] cameraTypes = new string[] { "CVseries100 ", "CVseries500" , "CVseries700" };
foreach (string cam in cameraTypes)
{
camera_type.Items.Add(cam);
}
//*******select your trigger mode( default is set to NONE)*******
string[] triggerModes = new string[] { "triggerModeNone", "triggerModeDATA", "triggerModeRepeat" };
foreach(string trigger in triggerModes)
{
trigger_mode.Items.Add(trigger);
}
//*****put a default value for thresHold********
threshold_value.Text = thresHold;
//*******add values to the baudrate dropdown********
baud_rate.Items.Add("9600");
baud_rate.Items.Add("19200");
baud_rate.Items.Add("38400");
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
public static void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
value = sp.ReadTo("\r");
string[] values = value.Split(new char[] { ',' });
x = values[0];
y = values[1];
match = values[2];
}
//public static void get_data()
//{
// port.Write("T");
//}
#region encapsulates all the individuals functions when the user changes settings ( UI interaction functions)
private void get_sample_Click(object sender, RoutedEventArgs e)
{
//write code to read x,y,threshold values in the text boxes
port.Write("T");
//MainWindow.get_data();
x_value.Text = string.Format("{0}", x);
y_value.Text = string.Format("{0}", y);
thresholdvalue.Text = string.Format("{0}", match);
}
#region the method opens a savefileDialog(dataFile) and lets user save the file in which data is stored
public void data_file_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog dataFile = new SaveFileDialog();
dataFile.DefaultExt = ".txt";
dataFile.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
dataFile.RestoreDirectory = true;
dataFile.Title = "select or create a new file";
DateTime currentTime = DateTime.Now;
dataFile.Filter = " Text Document |*.txt | Excel |*.xls";
string datepatt = @"M-d-yy_hh-mm_Data";
string saveDT = currentTime.ToString(datepatt);
dataFile.FileName = saveDT;
Nullable<bool> result = dataFile.ShowDialog();
if (result == true)
{
filePath = dataFile.FileName;
fileName = dataFile.SafeFileName;
}
System.IO.FileStream fs = (System.IO.FileStream)dataFile.OpenFile();
using (StreamWriter Write = new StreamWriter(fs))
{
Write.WriteLine("Wafer Placement Data\n\n");
Write.WriteLine("File Name : {0}\n", fileName);
Write.WriteLine("Port Name : COM4\n");
Write.WriteLine("Threshold : {0}\n", threshold_value.Text);
Write.WriteLine("Date : {0}\n\n", Convert.ToString(DateTime.Now));
//************Print Header to the file******************
Write.WriteLine("\tX\tY\tcorrelation\tDate\n");
}
}
#endregion
#region function called when the threshold value is changed
private void threshold_value_TextChanged(object sender, TextChangedEventArgs e)
{
thresHold = threshold_value.Text;
}
#endregion
#region function to write individual data points on the window for checking
private void writeSample(double X, double Y, double threshold)
{
FileStream file = new FileStream(filePath, FileMode.Append, FileAccess.ReadWrite);
using (StreamWriter Writer = new StreamWriter(file))
{
Writer.WriteLine(DateTime.Now);
Writer.WriteLine("\t X \t Y\t threshold% ");
}
}
#endregion
private void run_button_Click(object sender, RoutedEventArgs e)
{
do
{
port.Write("T");
FileStream file = new FileStream(filePath, FileMode.Append, FileAccess.Write);
Thread.Sleep(500);
using (StreamWriter Writer = new StreamWriter(file))
{
Writer.WriteLine("\t{0}\t{1}\t{2}\t{3}", x, y, match, Convert.ToString(DateTime.Now));
}
port.DiscardInBuffer();
} while (STOP);
}
private void stop_button_Click(object sender, RoutedEventArgs e)
{
STOP = false;
}
private void command_TextChanged(object sender, TextChangedEventArgs e)
{
string C = command.Text;
port.WriteLine(C);
}
#endregion
}
}
You need to run your serial port code in separate thread. In your implementation GUI thread is busy w/ serial port communication that is why your window is frozen. The following article explains exactly what you need:
http://www.ryanvice.net/wpf-3-5/using-backgroundworker-with-wpf/