Последовательный порт связи между потоками - PullRequest
2 голосов
/ 15 июля 2011

После долгих исследований я все еще в тупике.У меня есть объект последовательного порта, который постоянно читает данные.Что я могу сделать, это сгенерировать событие 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 ]

2 голосов
/ 15 июля 2011
  1. Вашему классу RadiometerILT1700 требуется event, чтобы сообщить о полученных (и обработанных) данных.
  2. Ваша форма подписывается на это событие
  3. Обработчик событий Forms использует this.Invoke() для преодоления проблемы с многопоточностью.
1 голос
/ 15 июля 2011

Invoke - это метод для Delegate или Form или Control, поскольку csRadiometerILT1700 не является ни одним из них, он не наследует реализацию Invoke от этих классов.

YouВам нужно будет вызвать другое событие для вызывающего csRadiometerILT1700 и указать, что где-то в вашем GUI (вместе с любыми проблемами с несколькими потоками.) В качестве альтернативы, вы могли бы предоставить csRadiometerILT1700 делегат, который он мог бы использовать для обратного вызова, вроде каксобытие hand roll.

Получив данные в своей форме, вы можете использовать Control.InokeRequired для обнаружения ситуации с несколькими потоками и Control.Invoke для вызова с несколькими потоками.

0 голосов
/ 15 июля 2011

Вы не должны вызывать this.Invoke там, то, как вы делаете это, все равно что пытаться синхронизировать свой собственный поток с собственным вместо пользовательского интерфейса. Вы должны позвонить formhandle.Invoke, или в регистр класса формы для события, а затем вы можете использовать this.invoke

0 голосов
/ 15 июля 2011

Предполагается, что ошибка действительно:

Имя элемента управления, доступ к которому получен из потока, отличного от потока, в котором он был создан.

Проблема в том, что вы не можетеповлиять на ваш графический интерфейс из другого потока.Вам нужно вызвать форму или элемент управления, чтобы передать управление, чтобы его можно было изменить.Вы должны иметь возможность взаимодействовать с большинством других элементов, но не с формой.

0 голосов
/ 15 июля 2011

каждый раз, когда вы пытаетесь опубликовать сообщение в другой теме, вы получите эту ошибку. Вам необходимо использовать делегат и Invoke для элемента управления, который вы хотите вызвать из потока, который не является основным потоком формы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...