开发者

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?


  1. Your RadiometerILT1700 class needs an event to report it's received (and processed) data.
  2. Your Form subscribes to that event
  3. 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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜