线程之间的串口通信

时间:2011-07-15 15:47:45

标签: c# winforms multithreading serial-port

经过大量研究后,我仍然感到难过。我有一个连续读取数据的串口对象。我能做的是生成dataReceived事件,与端口通信,并将接收到的值输出到调试窗口。所以,我很确定这一切都在物理上工作。问题是当我尝试将串口输出传递给原始线程时,我收到一个错误。它说我不能有线程交叉谈话(或者那种效果)。我一直在尝试使用backgroundWorker,但我不确定这是我想要的解决方案加上我的新手技能,这有点过头了。我尝试使用invoke但该方法似乎不可用。 (我可能是从错误的对象打来的?)无论如何部分在下面。

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));
                }
            }
        }

    }
}

当我使用代码

形成加载时,这都被调用了
            csRadiometerILT1700 Radiometer;

            ...

            Radiometer = new csRadiometerILT1700();
            Radiometer.openPort();

感谢任何见解。

编辑: 我将我的csRadiometerILT1700构造函数改为

   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);
    }

并声明

public event Delegate DataReceived;

在csRadiometerILT1700课程中。但这给了我“Datareceived必须属于委托类型”的错误。我现在如何解决这个问题?我是在正确的轨道上吗?

5 个答案:

答案 0 :(得分:2)

  1. 您的RadiometerILT1700课程需要event来报告其已收到(和已处理)的数据。
  2. 您的表单订阅该活动
  3. Forms事件处理程序使用this.Invoke()来克服交叉线程问题。

答案 1 :(得分:1)

InvokeDelegateFormControl上的一种方法,因为csRadiometerILT1700不是这些方法,它不会继承Invoke实现那些课程。

您需要向csRadiometerILT1700的调用者发送另一个事件,并在某个地方使用GUI(以及任何交叉线程问题)。或者,您可以向csRadiometerILT1700提供一个代理人用来回调,有点像手卷活动。

在表单中获得数据后,可以使用Control.InokeRequired检测跨线程情况,使用Control.Invoke进行跨线程调用。

答案 2 :(得分:0)

任何时候你尝试从不同的线程发布到主线程,你会得到这个错误。您需要在要从非主表单线程的线程调用的控件上使用委托和Invoke。

答案 3 :(得分:0)

假设错误实际上是:

  

从线程以外的线程访问控制控件名称   是在。上创建的。

问题是你不能从另一个线程影响你的GUI。您需要invoke表单或控件来传递控件,以便对其进行修改。您应该能够与大多数其他元素进行交互,但不能与表单进行交互。

答案 4 :(得分:0)

你不应该在那里调用this.Invoke,你这样做的方式就像试图用你自己的自己的线程同步UI一样。你应该致电formhandle.Invoke,或者在活动的表格类注册表内,然后你可以使用this.invoke