So I've recently come across a what I think is a deadlock that only happens sometimes. After I close my form the app just hangs. I'm using SerialPorts for communication. I've read this answer and this answer which both suggest I use BeginInvoke()
instead of Invoke()
for most methods unless I need to wait for a control to update.
- I don't know if this makes sense but I'm trying to figure out how to make the bug happen every time I close the form, so that if its resolved by using
BeginInvoke
I'm sure its gone. My code to close the port is
private void closeDevicePort()
{
if (devicePort != null)
{
try
{
setMode("D0");
toggleAllBtns();
devicePort.Close();
devicePort = null; //sometimes doesn't get past here
Console.WriteLine("closing++++ here");
}
catch (Exception ex) {
Console.WriteLine(ex);
}
//devicePort = null;
}
}
which gets called through a GUIForm_FormClosed
event on FormClosed
. How do I make this happen every time to test that changing to BeginInvoke()
actually works for my winforms app?
Also here is my DataReceivedHandler
where I set the devicePort (which I didn't think was making anything explicitly multi-threaded)
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort serialPort1 = (SerialPort)sender;
if (serialPort1.IsOpen)
{
try
{
string message = serialPort1.ReadLine();
if (devicePort == null)
{
devicePort = serialPort1;
}
}catch(Exception ex)
{
Console.WriteLine(ex);
}
}
}
- I have a
plotData()
function which plots data in realtime. Is usingBeginInvoke()
instead ofInvoke()
fine here too?
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort serialPort1 = (SerialPort)sender;
if (serialPort1.IsOpen)
{
try
{
string message = serialPort1.ReadLine();
Console.WriteLine(message);
if (message.Substring(0, 1) == "!")
{
oldTime = newTime;
//checkPortsTimer.Stop();
//checkPortsTimer.Interval = 1500;
//checkPortsTimer.Start();
}
string flag = message.Substring(1, 1);
string command = message.Substring(2, 1);
string package = message.Substring(3);
switch (flag)
{
case "S":
switch (command)
{
case "C": //ready mode
setMode("SC");
if (devicePort == null)
{
addDevicePort(serialPort1);
}
break;
}
break;
case "D": //data stream
float[] data = Array.ConvertAll(package.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries), float.Parse);
txtData_Update(data);
plotData(data);
break;
default:
Console.WriteLine("not a recognised command. Try Again");
break;
}
}
catch (Exception ex)
{
Console.WriteLine("in data received exception handler");
Console.WriteLine(ex);
}
}
}