Войти

Показать полную графическую версию : Работа с потоками. Чтение из COM-порта


Tonny_Bennet
16-02-2012, 16:01
Здравствуйте.

Пишу на 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
вот тут
http://msdn.microsoft.com/ru-ru/library/system.io.ports.serialport.datareceived.aspx
об этом написано

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

Tonny_Bennet
20-02-2012, 16:19
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
Tonny_Bennet, я же тебе написал решение проблемы. Там даже код есть. Внедряешь его себе и пишешь спокойно дальше многопоточный код. Ну или идешь кривым путем и перед вызовом вывода сообщений пишешь Control.CheckForIllegalCrossThreadCalls = false; (об этом тоже есть в приведенной мной ссылке).




© OSzone.net 2001-2012