Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Работа с потоками. Чтение из COM-порта (http://forum.oszone.net/showthread.php?t=228009)

Tonny_Bennet 16-02-2012 16:01 1860230

Работа с потоками. Чтение из COM-порта
 
Здравствуйте.

Пишу на C# программу, которая будет общаться с ком портом. Создал форму. Добавил в неё объект SerialPort. Программа открывает порт. Записывает в него данные. У порта есть событие DataReceived, которое как я понимаю наступает во время получения данных. Я хочу эти данные выводить на форму в RichTexBox (в коде rtb_log). Но в момент когда из порта должен прийти ответ возникает ошибка:

Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "rtb_log" не из того потока, в котором он был создан.

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


Вы не могли бы мне как можно проще и нагляднее пояснить как можно решить данную проблему? На пальцах попытаться объяснить как в данном случае работать с потоками...

Код:

        private void btn_open_port_Click(object sender, EventArgs e)
        {
            try
            {
                serialPort.PortName = "COM" + tb_com.Text;
                serialPort.Open();           
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message);
            }   
        }

        private void btn_write_Click(object sender, EventArgs e)
        {
            try
            {
                string s = tb_write.Text + "\r\n";
                serialPort.WriteLine(s);
                rtb_log.AppendText(s);
            }
          catch (Exception err)
            {
                MessageBox.Show(err.Message);
            } 
        }

        private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                byte[] b = new byte[128];
                serialPort.Read(b, 0, b.Length);             
                string s = Encoding.ASCII.GetString(b);
            }
            catch (Exception e3)
            {
                MessageBox.Show(e3.Message);
          }

        }


ferget 16-02-2012 16:15 1860239

вот тут
http://msdn.microsoft.com/ru-ru/libr...areceived.aspx
об этом написано

Delirium 17-02-2012 00:54 1860555

Tonny_Bennet, эта проблема была недавно описана в этом форуме. http://forum.oszone.net/thread-227336.html

Tonny_Bennet 20-02-2012 16:19 1862825

ferget, начал вчитываться... мне всё так же не понятна логика работы... пока не пойму логику не пойму что с чем завязать.

Поправьте меня если я не прав:

Сначала я записываю в порт массив из байт.
Затем обработчик событий serialPort_DataReceived срабатывает при приходе сообщения с порта.
В теле обработчика я запускаю чтение того количества элементов массива, которые есть в буфере приёма serialPort.BytesToRead.
Но когда в этом же обработчике я пытаюсь записать считанные байты в элемент формы мне вылетает ошибка: попытка доступа к элементу управления "rtb_log" не из того потока, в котором он был создан.
Может мне нужно после прочтения сообщения создать событие: "Сообщение прочитано: текст сообщения"
А для rtb_log сделать обработчик событий который будет ловить эти сообщение и выписывать в форму?


Расскажите пожалуйста как это сделать правильно....

P.S. Язык MSDN не всегда понятен

В примере

Код:


    private static void DataReceviedHandler(
                        object sender,
                        SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string indata = sp.ReadExisting();
        Console.WriteLine("Data Received:");
        Console.Write(indata);
    }

Всё создаётся в консоли и наверное из-за этого не возникает ошибки связанной с потоками

Delirium 21-02-2012 01:08 1863161

Tonny_Bennet, я же тебе написал решение проблемы. Там даже код есть. Внедряешь его себе и пишешь спокойно дальше многопоточный код. Ну или идешь кривым путем и перед вызовом вывода сообщений пишешь
Код:

Control.CheckForIllegalCrossThreadCalls = false;
(об этом тоже есть в приведенной мной ссылке).


Время: 05:12.

Время: 05:12.
© OSzone.net 2001-