Arduino Microcontrollers interfacing C# - c#

I'm working on project and I need to create a program that gets data from an Arduino to determine the status all sensors values. I've researched that the best way to send these data is to send them in one line through the serial port and then parse it in Visual Studio. The problem is I don't know how to parse the said data in order for them to show in different text boxes in the program. Any help would be much appreciated...in one textbox am already showing the data but I want to show all sensors values in different textboxes.
namespace Arduino_Data
{
public partial class Form1 : Form
{
private SerialPort myport;
private DateTime datetime;
private string in_data;
public Form1()
{
InitializeComponent();
}
// private void label3_Click(object sender, EventArgs e)
// {
// }
private void satrt_btn_Click(object sender, EventArgs e)
{
myport = new SerialPort();
myport.BaudRate = 9600;
myport.PortName = port_name_tb.Text;
myport.Parity = Parity.None;
myport.DataBits = 8;
myport.StopBits = StopBits.One;
myport.DataReceived += myport_DataReceived;
try{
myport.Open();
data_tb.Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message , "Error");
}
}
void myport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//throw new NotImplementedException();
in_data = myport.ReadLine();
this.Invoke(new EventHandler(displaydata_event));
}
private void displaydata_event(object sender, EventArgs e)
{
// throw new NotImplementedException();
datetime = DateTime.Now;
string time = datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;
data_tb.AppendText( time + "\t\t\t"+in_data+"\n");
int data_value = Convert.ToInt32(in_data);
pb_value.Value = data_value;
pb_value.Minimum = 0;
pb_value.Maximum = 1023;
}
private void stop_btn_Click(object sender, EventArgs e)
{
try
{
myport.Close();
}
catch (Exception ex2)
{
MessageBox.Show(ex2.Message, "Error");
}
}
private void save_btn_Click(object sender, EventArgs e)
{
try {
string pathfile = #"C:\Users\irtaz\Desktop\DATA";
string filename = "arduino_data.txt";
System.IO.File.WriteAllText(pathfile + filename, data_tb.Text);
MessageBox.Show("Data has been saved to" + pathfile, "Save File");
}
catch(Exception ex3)
{
MessageBox.Show(ex3.Message, "Error");
}
}
}
}

Related

Serial Communication (C# Windows Forms)

Okay so I'm trying to do a two-way communication from C# to Arduino (using FTDI232) and viceversa, from Arduino to C#.
Here's the code:
public partial class Form1 : Form
{
public SerialPort myPort;
private DateTime dateTime;
private string inData;
const string com = "COM8";
public Form1()
{
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e) // TURN ON LED
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
try
{
myPort.Open();
myPort.WriteLine("A");
myPort.Close();
error_tb.Text = "";
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Errore");
}
}
private void stop_btn_Click(object sender, EventArgs e) // TURN OFF LED
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
try
{
myPort.Open();
myPort.WriteLine("B");
myPort.Close();
error_tb.Text = "";
}
catch (Exception exc2)
{
MessageBox.Show(exc2.Message, "Error");
}
}
void MyPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
inData = myPort.ReadLine();
this.Invoke(new EventHandler(displayData_event));
}
private void displayData_event(object sender, EventArgs e)
{
dateTime = DateTime.Now;
string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
values_tb.Text = time + "\t\t\t\t\t" + inData;
}
private void Form1_Load(object sender, EventArgs e) // PRESS PHYSICAL BUTTON TO SEND DATA
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
myPort.Parity = Parity.None;
myPort.DataBits = 8;
myPort.StopBits = StopBits.One;
myPort.DataReceived += MyPort_DataReceived;
try
{
myPort.Open();
values_tb.Text = "";
}
catch (Exception exc3)
{
MessageBox.Show(exc3.Message, "Error");
}
}
private void exit_btn_Click(object sender, EventArgs e) // Exit from Application
{
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
}
I have three problems. One is when I want to close the application, I want the Serial Communication to turn off, because I made it automatically open using Form1_Load, as soon as you start the debug, it also opens Serial Communication, and it remains on, but I don't want to use a button that I have to click first to close the application. I need to close Serial Communication automatically after I close the application.
The second problem is with the Serial Port that denies the communication, what I mean is that I need to switch from Receiving Data to Sending Data. Here's a picture of what it looks like: Application Image
The the third problem is the LED one. Well its similar to the second one, but this time when I click the button OFF, I want it to switch back to Receiving Data. Here's the picture:
Application Image 2
EDIT : This code is only temporary. I needed it to turn off the Serial Communication
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
You are initializing and opening the port many times. This is not allowed. Use a single initialization and keep the member. This makes the code much smoother, too.
public partial class Form1 : Form
{
public SerialPort myPort;
private DateTime dateTime;
const string com = "COM8";
public Form1()
{
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e) // TURN ON LED
{
try
{
myPort.WriteLine("A");
error_tb.Text = "";
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Errore");
}
}
private void stop_btn_Click(object sender, EventArgs e) // TURN OFF LED
{
try
{
myPort.WriteLine("B");
error_tb.Text = "";
}
catch (Exception exc2)
{
MessageBox.Show(exc2.Message, "Error");
}
}
void MyPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var inData = myPort.ReadLine(); // Use local variable
Invoke(new Action<string>(displayData_event), inData);
}
private void displayData_event(string data)
{
dateTime = DateTime.Now;
string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
values_tb.Text = time + "\t\t\t\t\t" + data;
}
private void Form1_Load(object sender, EventArgs e) // PRESS PHYSICAL BUTTON TO SEND DATA
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
myPort.Parity = Parity.None;
myPort.DataBits = 8;
myPort.StopBits = StopBits.One;
myPort.DataReceived += MyPort_DataReceived;
try
{
myPort.Open();
values_tb.Text = "";
}
catch (Exception exc3)
{
MessageBox.Show(exc3.Message, "Error");
}
}
private void exit_btn_Click(object sender, EventArgs e) // Exit from Application
{
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
myPort = null;
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
}
I think I also fixed your event handling. One handler that gets the data and then forwards the received text is enough. You would also not really require the exception handling around WriteLine now, since that cannot really fail.

C# - Change format of Data received from Serial Port

I am making a C# form application that receives data from an instrument communicating at Baud Rate 2400, parity None, 8 bit data, 1 stop bit.
The data is coming in a continuous string line in the form [000000][000000][000000]. For example if during a procedure the reading on the instrument is varying like 0.50,0.49,0.72,0.61,0.48 then the string of received data would be [000050][000049][000072][000061][000048], which is how it is currently being displayed in the textbox.
I need to display the Maximum value reached during a procedure into the textbox and in the correct format, like in this case it should be 0.72. I am at a loss about what would be the code for that.
Below is my current code for serial port communication.
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void Main_Load(object sender, EventArgs e)
{
}
//this is the button to open port.
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = true;
try
{
serialPort1.PortName = comboBox1.Text;
serialPort1.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
//Event handler for data received.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Regex rx = new Regex(#"\[(\d+)\]");
double.TryParse(richTextBox2.Text, out double max);
foreach (Match match in rx.Matches(indata))
{
double val = int.Parse(match.Groups[1].Value) / 100.0;
if (val > max)
max = val;
}
richTextBox2.Text = max.ToString();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
//this is the button to close port
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = true;
button2.Enabled = false;
try
{
serialPort1.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void button3_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.DataReceived += DataReceivedHandler;
}
else
{
MessageBox.Show("Error : Port needs to be open or wrong port selected!");
}
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (serialPort1.IsOpen)
serialPort1.Close();
}
private void button4_Click(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
comboBox1.Items.AddRange(ports);
comboBox1.SelectedIndex = 0;
button2.Enabled = false;
}
So you want to process data every time there is data to process right?
If you are using the "System.IO.Ports", and your serialPort1 is of the type SerialPort, you have the "DataReceived" event available. So after you instantiate the serialPort1 you can:
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = true;
try
{
//check and set the settings of your device
serialPort1 = new SerialPort
{
PortName = comboBox1.Text,
BaudRate = 2400,
Parity = Parity.None,
StopBits = StopBits.Odd,
DataBits = 8,
Handshake = Handshake.None,
RtsEnable = true
};
serialPort1.DataReceived += DataReceivedHandler;
serialPort1.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Then you just need to declare the event handler, something like this:
private void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Regex rx = new Regex(#"\[(\d+)\]");
double.TryParse(textBox13.Text, out double max);
foreach (Match match in rx.Matches(indata))
{
double val = int.Parse(match.Groups[1].Value) / 100.0;
if (val > max)
max = val;
}
textBox13.Text = max .ToString();
}
This will compare the values received and the current value in the textbox.
If I understand you're formatting requirement correctly you basically want to remove zeros at the front from each of the numbers and then compare them to find the max value and display them in the format of x.xx If that's the case create a separate method to handle it like this:
private decimal GetMaxReading(string rawReadingData)
{
decimal maxReading = 0;
var readings = rawReadingData.Split('[',).ToList();
foreach (var reading in readings)
{
var readingString = reading.TrimStart('0')
.TrimEnd(']');
var isInt = int.TryParse(readingString, out int readingValue);
var value = isInt ? (decimal)readingValue / 100 : 0;
maxReading = value > maxReading ? value : maxReading;
}
return maxReading;
}

C# textfile only contains last string written to file with StreamWriter

I'm writing a Chat Program in C# (Windows Forms Application), the solution contains to projects which both consist of one form ( see picture ). While sending messages to each other works, I'm trying to record the conversation session in a .txt file named dateTime.txt using StreamWriter. Creating the file if it does not exist yet works, but whenever I open the text file, it only contains the last string that was written to it instead of containing the whole "conversation".
Does anybody know how to fix this?
This is the code of one of the forms, but since the forms do exactly the same, the code is the same too so i'm only posting the code of one Form. Would be great if somebody knows what I have to change so the whole conversation is recorded in the text file.
namespace Assignment3Client
{
public partial class Chat : Form
{
NamedPipeClientStream clientPipe = new NamedPipeClientStream("pipe2");
NamedPipeServerStream serverPipe = new NamedPipeServerStream("pipe1");
string msg = String.Empty;
string msgStr;
string name;
byte[] ClientByte;
public Chat()
{
InitializeComponent();
}
private void btnStartChat_Click(object sender, EventArgs e)
{
this.Text = "Waiting for a connection....";
if (txtBoxName.Text.Length == 0)
{
MessageBox.Show("please enter a name first.");
}
else
{
name = txtBoxName.Text;
clientPipe.Connect();
serverPipe.WaitForConnection();
if (serverPipe.IsConnected)
{
this.Text = "You are connected, " + name + "!";
btnStartChat.Enabled = false;
btnSend.Enabled = true;
txtBoxMsg.Enabled = true;
txtBoxMsg.Focus();
receiveWorker.RunWorkerAsync();
}
}
}
private void btnSend_Click(object sender, EventArgs e)
{
msg = "[" + name + ": " + DateTime.Now + "] " + txtBoxMsg.Text;
txtBoxChat.AppendText(msg + "\n");
FileWriter(msg);
sendWorker.RunWorkerAsync(msg); //start backgroundworker and parse msg string to the dowork method
txtBoxMsg.Clear();
txtBoxMsg.Focus();
}
private void sendWorker_DoWork(object sender, DoWorkEventArgs e)
{
Byte[] msgByte = System.Text.Encoding.GetEncoding("windows-1256").GetBytes(msg);
serverPipe.Write(msgByte, 0, msg.Length);
}
private void receiveWorker_DoWork(object sender, DoWorkEventArgs e)
{
ClientByte = new Byte[1000];
int i;
for (i = 0; i < ClientByte.Length; i++)
{
ClientByte[i] = 0x20;
}
clientPipe.Read(ClientByte, 0, ClientByte.Length);
msgStr = System.Text.Encoding.GetEncoding("windows-1256").GetString(ClientByte);
receiveWorker.ReportProgress(i, msgStr);
}
private void receiveWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if ((string)e.UserState == String.Empty)
{ MessageBox.Show("no message"); }
else
{
string message = (string)e.UserState;
txtBoxChat.AppendText(message);
FileWriter(message);
txtBoxChat.BackColor = System.Drawing.Color.DarkBlue;
txtBoxChat.ForeColor = System.Drawing.Color.White;
}
}
private void receiveWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (clientPipe.IsConnected)
{
receiveWorker.RunWorkerAsync();
}
else
{
txtBoxMsg.Enabled = false;
btnSend.Enabled = false;
MessageBox.Show("Connection lost");
}
}
private void Chat_Activated(object sender, EventArgs e)
{
txtBoxChat.BackColor = new System.Drawing.Color();
txtBoxChat.ForeColor = new System.Drawing.Color();
}
private void exitMenuStrip_Click(object sender, EventArgs e)
{
this.Close();
}
private void conMenuSrip_Click(object sender, EventArgs e)
{
}
private void errMenuStrip_Click(object sender, EventArgs e)
{
}
public void FileWriter(string message)
{
string path = #"C:\Users\selin\Documents\TAFE\Term 3\dateTime.txt";
FileStream conLog;
if (!File.Exists(path))
{
conLog = new FileStream(path, FileMode.Create);
}
else
{
conLog = new FileStream(path, FileMode.Open);
}
StreamWriter writer = new StreamWriter(conLog);
writer.WriteLine(message);
writer.AutoFlush = true;
writer.Close();
MessageBox.Show("written to file" + message);
}
}
}
in FileWriter(string message) change
conLog = new FileStream(path, FileMode.Open);
to
conLog = new FileStream(path, FileMode.Append);

How to plot graphs with data from a SerialPort with multiple sensors

I need to plot data from sensors of pH, Temperature and Humidity, the data is sent as a matrix from arduino to PC through the serial port.
I can show the data in a TextBox, but when I try to plot the data, it doesn't work (I don't know how to do it).
I just can plot the data when is not a matrix and it's data from just one sensor.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Windows.Forms.DataVisualization.Charting;
namespace grafik1
{
public partial class Form1 : Form
{
private SerialPort sensport;
private DateTime datetime;
private string data;
private string data2;
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.DataSource = SerialPort.GetPortNames();
timer1.Start();
}
double rt = 0;
Boolean i = false;
private void timer1_Tick(object sender, EventArgs e)
{
rt = rt + 0.1;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
sensport.Close();
}
private void button1_Click(object sender, EventArgs e)
{
if (comboBox2.Text == "")
{
MessageBox.Show("Error");
}
else
{
sensport = new SerialPort();
sensport.BaudRate = int.Parse(comboBox2.Text);
sensport.PortName = comboBox1.Text;
sensport.Parity = Parity.None;
sensport.DataBits = 8;
sensport.StopBits = StopBits.One;
sensport.Handshake = Handshake.None;
sensport.DataReceived += sensport_DataReceived;
try
{
sensport.Open();
textBox1.Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}
}
void sensport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (i == false)
{
rt = 0;
i = true;
}
data = sensport.ReadLine();
this.chart1.Series["Data1"].Points.AddXY(rt, data);
this.Invoke(new EventHandler(displaydata_event));
}
private void displaydata_event(object sender, EventArgs e)
{
datetime = DateTime.Now;
string time = datetime.Day + "/" + datetime.Month + "/" + datetime.Year + "\t" + datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;
txtData.AppendText(time + "\t" + data + "\n");
}
private void button2_Click(object sender, EventArgs e)
{
string directorio = textBox1.Text;
if (directorio == "")
{
MessageBox.Show("Error");
}
else {
try
{
string kayıtyeri = #"" + directorio + "";
this.chart1.SaveImage(("+kayityeri+"), ChartImageFormat.Png);
MessageBox.Show("Grafica guardada en " + kayıtyeri);
}
catch (Exception ex3)
{
MessageBox.Show(ex3.Message, "Error");
}
}
}
private void label4_Click(object sender, EventArgs e)
{
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
sensport.Close();
}
private void button4_Click(object sender, EventArgs e)
{
try
{
string pathfile = #"C:\Users\MARIO GONZALEZ\Google Drive\VisualStudio\Arduino0_1\DATA";
string filename = "arduinoRTPv1.xls";
System.IO.File.WriteAllText(pathfile + filename, txtData.Text);
MessageBox.Show("Data saved");
}
catch (Exception ex3)
{
MessageBox.Show(ex3.Message, "Error");
}
}
private void button5_Click(object sender, EventArgs e)
{
}
private void chart1_Click(object sender, EventArgs e)
{
}
}
}
Let's assume you have prepared your chart, maybe like this:
chart1.Series.Clear();
chart1.Series.Add("ph");
chart1.Series.Add("Temp");
chart1.Series.Add("Hum");
chart1.Series["ph"].ChartType = SeriesChartType.Line;
chart1.Series["Temp"].ChartType = SeriesChartType.Line;
chart1.Series["Hum"].ChartType = SeriesChartType.Line;
chart1.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;
chart1.ChartAreas[0].AxisY2.Title = "Temp";
chart1.ChartAreas[0].AxisY2.Maximum = 100;
Now you can add a string that contains some data blocks as shown in the comments..
string data = "7.5 23.8 67 \n8.5 23.1 72 \n7.0 25.8 66 \n";
..like this:
var dataBlocks = data.Split('\n');
foreach (var block in dataBlocks)
{
var numbers = block.Split(new [] {' '}, StringSplitOptions.RemoveEmptyEntries);
// rt += someTime; (*)
for (int i = 0; i < numbers.Length; i++)
{
double n = double.NaN;
bool ok = double.TryParse(numbers[i], out n);
if (ok) chart1.Series[i].Points.AddXY(rt, n);
else
{
int p = chart1.Series[i].Points.AddXY(rt, 0);
chart1.Series[i].Points[p].IsEmpty = true;
Console.WriteLine("some error message..");
}
}
}
I have modified the data a little to show the changes a little better..
Note that I left out the counting up of your timer rt, which is why the chart shows the points with indexed x-values. For a real realtime plot do include it maybe here (*) !
If you keep adding data your chart will soon get rather crowded.
You will then either have to remove older data from the beginning or at least set a minimum and maximum x-values to restrict the display to a reasonably number of data points and or turn on zooming!
See here here and here for some examples and discussions of these things!

C# Batch file output problems

I have been working on a manager application for a Minecraft server, when I run my program, the console shows and disappears, if I run it manually, it runs without and problems.
Batch file code:
java -Xmx1024M -jar craftbukkit-1.7.2-R0.3.jar -o false
My full code (MessageBoxes are in Polish, becouse im from Poland, but later i will add support for other languages):
using System;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Process server;
private Boolean runServer()
{
if (!File.Exists(textBox2.Text))
{
MessageBox.Show("Brak określonej ścieżki dostępu! (" + textBox2.Text + ")", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
Process process = new Process
{
StartInfo =
{
FileName = textBox2.Text,
//Arguments = textBox3.Text,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = false,
}
};
process.OutputDataReceived += new DataReceivedEventHandler(server_outputDataReceived);
process.ErrorDataReceived += new DataReceivedEventHandler(server_outputDataReceived);
server = process;
if (process.Start())
return true;
else
{
MessageBox.Show("Nie można włączyć serwera!", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
private String ReadFile(String filename, int line)
{
StreamReader reader = new StreamReader(filename);
for (int i = 0; i < line; i++)
{
reader.ReadLine();
}
return reader.ReadLine();
}
private void ReloadOPs()
{
if (!File.Exists(textBox1.Text))
{
MessageBox.Show("Sciezka dostępu do pliku z listą graczy posiadających OP nie istnieje! (" + textBox1.Text + ")", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
tabControl1.SelectedTab = tabPageOptions;
textBox1.SelectAll();
return;
}
String line = ReadFile(textBox1.Text, 0);
comboBox1.Items.Clear();
for (int i = 1; i < File.ReadAllLines(textBox1.Text).Length; i++)
{
if (!String.IsNullOrWhiteSpace(ReadFile(textBox1.Text, i)))
{
comboBox1.Items.Add(line);
line = ReadFile(textBox1.Text, i);
}
}
MessageBox.Show("Lista graczy z OP, została odświeżona.");
}
// OPs combobox (OPs)
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
groupBox1.Text = comboBox1.SelectedItem.ToString();
groupBox1.Visible = true;
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.Text = Application.StartupPath.ToString() + #"\ops.txt";
ReloadOPs();
}
// Reload OPs button (OPs)
private void button1_Click(object sender, EventArgs e)
{
ReloadOPs();
}
// Save button (Options)
private void button4_Click(object sender, EventArgs e)
{
}
private void server_outputDataReceived(object sender, DataReceivedEventArgs e)
{
addConsoleMessage(e.Data.ToString(), true);
}
// Run server button (Menu)
private void button5_Click(object sender, EventArgs e)
{
if (!runServer())
return;
server.BeginOutputReadLine();
button6.Enabled = true;
}
// Stop server button (Menu)
private void button6_Click(object sender, EventArgs e)
{
if(!server.HasExited)
server.Kill();
button6.Enabled = false;
}
private void addConsoleMessage(String message, Boolean refresh)
{
listBox1.Items.Add(message);
if (refresh)
listBox1.Refresh();
}
}
}
My problem is that program crashes becouse InvaildOperationException was unhandled (listBox1.Items.Add(message) in addConsoleMessage).
External error information: Invalid operation between threads: the control 'listBox1' is accessed from a thread other than the thread it was created.
You cannot update UI form background thread. Try this
WPF
private void server_outputDataReceived(object sender, DataReceivedEventArgs e)
{
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, () =>
{
addConsoleMessage(e.Data.ToString(), true);
});
}
Update
In WinForms the Invoke/BeginInvoke methods are directly on the control objects as you can see from the docs of System.Windows.Forms.Control. So you'd have listBox1.BeginInvoke(...) for example.

Categories