My program is suppose to perform tests on 8 electronic products of the same model simultaneously. The previous programmer has implemented some form of multi-threading in the program to accomplish this. However, when 5 slots or more are being tested, the UI becomes unresponsive and the results being written to a text file may get corrupted.
Below I will insert a pseudo-code on what's going on in the program.
private void button1_Click(object sender, EventArgs e)
{
//create_thread_1 <= mainFunction 1
//start thread 1
}
private void button2_Click(object sender, EventArgs e)
{
//create_thread_2 <= mainFunction 2
//start thread 2
}
private void button3_Click(object sender, EventArgs e)
{
//create_thread_3 <= mainFunction 3
//start thread 3
}
private void mainFunction1
{
//perform test A
//write test A result to textFile1 //calls writeToTextFile1
//perform test B
//write test B result to textFile1 //calls writeToTextFile1
//continues on and finishes all tests
//aborts thread1
//end
}
private void mainFunction2
{
//perform test A
//write test A result to textFile2 //calls writeToTextFile2
//perform test B
//write test B result to textFile2 //calls writeToTextFile2
//continues on and finishes all tests
//aborts thread2
//end
}
private void mainFunction3
{
//perform test A
//write test A result to textFile3 //calls writeToTextFile3
//perform test B
//write test B result to textFile3 //calls writeToTextFile3
//continues on and finishes all tests
//aborts thread3
//end
}
private void writeToTextFile1
{
//creates and saves results into textFile1
}
private void writeToTextFile2
{
//creates and saves results into textFile2
}
private void writeToTextFile3
{
//creates and saves results into textFile3
}
My theory is that only a single thread can open and write data into a text file at a single time, so when another thread have to write data, that thread has to wait and causes the UI to become unresponsive. Am I right here? If I'm not, any advice is greatly appreciated.
One of the solutions that I have read online is to declare the WriteToTextFile function as a new Thread so that other main threads can wait for each other without slowing down the UI. Is this the correct approach?
EDIT: added the important parts of the coding for better understanding..This code runs for one slot only but the other 9 slots basically uses the same code here
private void button1_Click(object sender, EventArgs e)
{
if (this.button1.Text == "START")
{
this.txtSerial1.ReadOnly = false;
this.txtSerial1.Select();
MessageBox.Show("SLOT 1: Scan the serial number and press ENTER", "3458A
Heat Rack", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
else if (System.Windows.Forms.DialogResult.OK == MessageBox.Show("SLOT 1: Are
you sure about stopping?", "3458A Heat Rack",
MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation))
{
this.call_main1.Abort();
this.sentry1.Close();
this.sentry1.Dispose();
MessageBox.Show("SLOT 1: Unit can be safely removed now", "3458A Heat
Rack", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
this.txtSerial1.Clear();
this.txtStart1.Clear();
this.txtStatus1.Clear();
this.info1.Clear();
this.button1.Text = "START";
this.button1.BackColor = this.startColour;
this.txtStatus1.BackColor = Control.DefaultBackColor;
}
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
int num;
int test_num = default(int);
double resultrelay = default(double);
if (e.KeyChar == '\r')
{
if (this.txtSerial1.Text.Length == 0)
{
this.txtSerial1.ReadOnly = true;
}
else if (this.txtSerial1.Text.Length >= 10)
{
try
{
this.sentry1 = new DirectIO(string.Concat("GPIB",
this.busNumber_Slot1, "::22::INSTR"));
this.terminal1 = new DirectIO(string.Concat("GPIB0::14::INSTR"));
num = 1;
}
catch (Exception exception)
{
num = 0;
}
if (num != 1)
{
MessageBox.Show("SLOT 1: DUT Not Present !!", "3458A Heat Rack",
MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
this.txtSerial1.Clear();
this.txtSerial1.Select();
this.txtSerial1.ReadOnly = true;
}
else
{
this.button1.Select();
this.button1.Text = "RUNNING";
this.button1.BackColor = this.runningColour;
this.txtSerial1.Text = this.txtSerial1.Text.ToUpper();
this.txtStart1.Text = DateTime.Now.ToString();
this.txtSerial1.ReadOnly = true;
string txtBox1_serial = this.txtSerial1.Text;
this.call_main1 = new Thread(() => this.main_Program_slot1(sentry1,
terminal1, txtBox1_serial, 1, test_num,
resultrelay));
this.call_main1.Start();
}
}
else
{
MessageBox.Show("SLOT 1: Unit Serial Number Is Incorrect!!", "3458A
Heat Rack", MessageBoxButtons.OK,
MessageBoxIcon.Asterisk);
this.txtSerial1.Clear();
this.txtSerial1.Select();
}
}
}
public void slot1(string test) //function to update GUI
{
if (!base.InvokeRequired)
{
this.info1.Text = test;
}
else
{
Form1.test1 updateTestType = new Form1.test1(this.slot1);
object[] objArray = new object[] { test };
base.Invoke(updateTestType, objArray);
}
}
private void write_TestResultDetails1(string serialnumber, double resultLatest1)
{
//update results into textfile
}
private void main_Program_slot1(DirectIO sentry1, DirectIO terminal1, string sernum, int slot_Number, int test_num, double resultrelay)
{
for (int i = 1; i <= loop_Count; i++)
{
slot1("TEST A");
//performs testA
//calls write_TestResultDetails1
slot1("TEST B");
//performs testB
//calls write_TestResultDetails1
}
}
Hope this coding can help you guys to understand my problem better.. PS: seems like changing to using BackGroundWorker instead of making my own threads will be a better choice for this kind of program.