Good day Everyone.
I'm busy trying to rewrite software that our company developed to read meters.
The code was originally made in visual basic 6 and I'm trying to rewrite it in C#, the problem is that neither myself or the person who wrote the original program are programmers we're Electrical Engineers.
Anyway I've got far with the program but I'm having an issue when killing the background worker in visual studio. If the meter doesn't read if I try to run the program again to read another meter I'll get an "Object Reference not set to an instant of an Object" in my communication window.
I think the issue is that the background worker is still running, the Error comes when I'm trying to SetText(newtext)
private void SetText(string text)
{
StringBuilder sb = new StringBuilder();
Dictionary<char, string> lSpecialDict
= new Dictionary<char, string>()
{
{ '\0', "<NUL>" }, {(char)0x01, "<SOH>" }, {(char)0x02, "<STX>" },
{(char)0x03, "<ETX>" }, {(char)0x04, "<EOT>" }, {(char)0x05, "<ENQ>" },
{(char)0x06, "<ACK>" }, {(char)0x07, "<BEL>" }, {(char)0x08, "<BS>" },
{(char)0x09, "<HT>" }, {(char)0x0A, "<LF>" }, {(char)0x0B, "<VT>" },
{(char)0x0C, "<FF>" }, {(char)0x0D, "<CR>" }, {(char)0x0E, "<SO>" },
{(char)0x0F, "<SI>" }, {(char)0x10, "<DLE>" }, {(char)0x11, "<DC1>" },
{(char)0x12, "<DC2>" }, {(char)0x13, "<DC3>" }, {(char)0x14, "<DC4>" },
{(char)0x15, "<NAK>" }, {(char)0x16, "<SYN>" }, {(char)0x17, "<ETB>" },
{(char)0x18, "<CAN>" }, {(char)0x19, "<EM>" }, {(char)0x1A, "<SUB>" },
{(char)0x1B, "<ESC>" }, {(char)0x1C, "<FS>" }, {(char)0x1D, "<GS>" },
{(char)0x1E, "<RS>" }, {(char)0x1F, "<US>" }, {(char)0x7F, "<DEL>" },
};
char[] charArr = text.ToCharArray();
foreach (char ch in charArr)
{
if (lSpecialDict.ContainsKey(ch))
{
string replacement;
lSpecialDict.TryGetValue(ch, out replacement);
sb.Append(replacement);
}
else
sb.Append(ch);
}
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (comwindow.txtInfo.InvokeRequired)
{
comwindow.Invoke((MethodInvoker)delegate
{
comwindow.txtInfo.Text += $"{sb} {Environment.NewLine}";
});
}
else
{
comwindow.txtInfo.Text += $"{sb} {Environment.NewLine}";
}
}
public void loadvalues(int PassID, Communication com)
{
BackgroundWorker LoadValues = new BackgroundWorker();
LoadValues.WorkerSupportsCancellation = true;
LoadValues.WorkerReportsProgress = true;
LoadValues.DoWork += LoadValues_DoWork;
LoadValues.RunWorkerCompleted += new RunWorkerCompletedEventHandler(LoadValues_RunWorkerCompleted);
LoadValues.RunWorkerAsync();
meterID = PassID;
comwindow = com;
}//load values
//Reads meter serial and loads values from Database
private void LoadValues_DoWork(object sender, DoWorkEventArgs e)
{
string newtext = $"Loading Value";
SetText(newtext);
Thread.Sleep(500);
GetMeterInfo meter = new GetMeterInfo();
DataTable dt = meter.GetMeterByID(meterID);
if (dt.Rows.Count > 0)
{
serial = dt.Rows[0]["Serial_Number"].ToString();
descr = dt.Rows[0]["Description"].ToString();
type = dt.Rows[0]["Meter_Type"].ToString();
ip = dt.Rows[0]["IP"].ToString();
tel = dt.Rows[0]["telephone_No"].ToString();
baud = int.Parse(dt.Rows[0]["Baud_Rate"].ToString());
address = int.Parse(dt.Rows[0]["Meter_Address"].ToString());
Pass = dt.Rows[0]["Meter_Password"].ToString();
Constant = int.Parse(dt.Rows[0]["Meter_Constant"].ToString());
port = int.Parse(dt.Rows[0]["Port"].ToString());
switch (baud)
{
case 300:
baudconvert = "0";
break;
case 600:
baudconvert = "1";
break;
case 1200:
baudconvert = "2";
break;
case 2400:
baudconvert = "3";
break;
case 4800:
baudconvert = "4";
break;
case 9600:
baudconvert = "5";
break;
default:
baudconvert = "5";
break;
}
}
}
private void BWComms_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker BWComms = (BackgroundWorker)e.Argument;
if (BWComms.CancellationPending)
{
e.Cancel = true;
}
int i = 1;
connection:
Thread.Sleep(500);
SetText("Connecting to meter... ".ToString());
BackgroundWorker helperBW = sender as BackgroundWorker;
helperBW.WorkerSupportsCancellation = true;
if (!helperBW.CancellationPending)
{
comwindow.statusInfo.Text = $"Meter Interigation Attempt {i}";
TcpClient tcpClient = new TcpClient();
client = tcpClient;
IPAddress ipAD = IPAddress.Parse(ip);
var result = tcpClient.BeginConnect(ipAD, port, null, null);
var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(3));
if (!success)
{
newtext = $"Failed to connect to Meter: {serial}";
SetText(newtext);
i++;
if (i == 4)// need to figure out how to cancel tcpconnection if cannot connect to meter.
{
SetText("Unable to connect to meter");
System.Windows.Forms.Application.ExitThread();
helperBW.CancelAsync();
}
goto connection;
Any advice on what I'm doing wrong or what I try would be appreciated.
Thank you