Serial port communication between threads
After much research I am still stumped. I have a serial port object which is reading data continuously. What I am able to do it generate the dataReceived event, communicate with the port, and output the received values to the debug window. So, I'm pretty sure it's all working physically. The problem is when I try to pass the serial port output to my origi开发者_JAVA百科nal thread I get an error. It says I can't have thread cross talk (or something to that effect). I've been trying to use a backgroundWorker but I'm not sure that is the solution I want plus with my novice skills it's a little over my head. And I tried to use invoke but the method doesn't seem to be available. (I might be calling from the wrong object?) Anyway section is below.
namespace Photometer
{
class csRadiometerILT1700
{
//manufacturer specs for baud rate, databits, and stop bits
static string portName="COM1";
static int baudRate = 1200;
static int dataBits = 8;
//instantialize a serial port object for the Radiometer
private SerialPort RadiometerSerial = new SerialPort(portName, baudRate, Parity.None, dataBits, StopBits.One);
//constructor
//public csRadiometerILT1700(Form ParentForm, Chart outputChart)
public csRadiometerILT1700()
{
//two handshaking properties of the ILT1700. Handshaking is enabled and
//http://stackoverflow.com/questions/6277619/problem-reading-serial-port-c-net-2-0-to-get-weighing-machine-output
RadiometerSerial.Handshake= Handshake.RequestToSend;
RadiometerSerial.DtrEnable = true;
RadiometerSerial.DataReceived += new SerialDataReceivedEventHandler(RadiometerSerial_DataReceived);
}
public void openPort()
{
if (!RadiometerSerial.IsOpen)
{
RadiometerSerial.Open();
}
}
public void closePort()
{
RadiometerSerial.Close();
}
string RadiometerVoltageReadingString;
int RadiometerVoltageReadingInt;
private void RadiometerSerial_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//It's here that this.invoke()... cannot be called.
RadiometerVoltageReadingString= (RadiometerSerial.ReadExisting().ToString()); //y-value
Debug.Print(RadiometerVoltageReadingString.ToString());
makeRadioReadingDouble(RadiometerVoltageReadingString);
}
private void makeRadioReadingDouble(string inputVoltageString)
{
List<double> outputVoltageDouble=new List<double>(2);
if (!(inputVoltageString == "\r\n" || inputVoltageString == ""))
{
string[] voltageValAndExpo = inputVoltageString.Split(new string[] { "e", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for (int inCounter = 0; inCounter < voltageValAndExpo.Count(); inCounter=inCounter+2)
{
double voltageVal = Convert.ToDouble(voltageValAndExpo[inCounter]);
double voltageExpo = Convert.ToDouble(voltageValAndExpo[inCounter + 1]);
outputVoltageDouble.Add(Math.Pow(voltageVal, voltageExpo));
}
}
}
}
}
This is all called when I form loads with the code
csRadiometerILT1700 Radiometer;
...
Radiometer = new csRadiometerILT1700();
Radiometer.openPort();
Any insight is appreciated.
EDIT: I altered my csRadiometerILT1700 constructor to
public csRadiometerILT1700(Form inputForm)
{
//inputForm.Invoke(
//two handshaking properties of the ILT1700. Handshaking is enabled and
//http://stackoverflow.com/questions/6277619/problem-reading-serial-port-c-net-2-0-to-get-weighing-machine-output
RadiometerSerial.Handshake= Handshake.RequestToSend;
RadiometerSerial.DtrEnable = true;
RadiometerSerial.DataReceived += new SerialDataReceivedEventHandler(RadiometerSerial_DataReceived);
inputForm.Invoke(DataReceived);
}
and declare
public event Delegate DataReceived;
in the csRadiometerILT1700 class. But this gives me the error of "Datareceived must be of a delegate type." How do I resolve this now? Am I on the right track?
- Your
RadiometerILT1700
class needs anevent
to report it's received (and processed) data. - Your Form subscribes to that event
- The Forms eventhandler uses
this.Invoke()
to overcome the cross-threading issue.
Invoke
is a method on a Delegate
or a Form
or Control
, since csRadiometerILT1700
is none of these it is not inheriting an Invoke implemenation from those classes.
You will need to raise another event to the caller of csRadiometerILT1700
and hadle that on you GUI somewhere (along with any cross thread issues.) Alternatively, you could provide csRadiometerILT1700
with a delegate it could use to callback, kind of like a hand rolled event.
Once you have the data in your Form you can use Control.InokeRequired
to detect a cross thread situation and Control.Invoke
to make the cross thread call.
anytime you try to post to the main thread from a different thread you'll get this error. You need to use a delegate and Invoke on the control you want to call from the thread that isn't the main form thread.
Assuming the error is actually:
Control control name accessed from a thread other than the thread it was created on.
The problem is you can't affect your GUI from another thread. You need to invoke the form or control to pass control so it can be modified. You should be able to interact with most other elements, but not a form.
You should not call this.Invoke
there, the way you are doing it is like trying to sync your own thread with your own instead with the UI. you should call formhandle.Invoke
, or inside form class register for the event and then you can use this.invoke
精彩评论