Название: потоки
Отправлено: demaker от Апрель 13, 2015, 13:31
В программе есть два потока Один поток работает на прием данных и из него при приеме высылается сигнал C++ (Qt) void RxThread::run() { forever{ if(!startThread){ qDebug()<<"Out of thread"; Q_EMIT receiveStop(); break; } int ret = CiWaitEvent(cw,1,500); //0.5sec if(ret > 0){ if(cw->rflags & CI_WAIT_RC){ canmsg_t msg_in; int retRd = CiRead(cw->chan,&msg_in,1); qDebug()<<"Read well done "<<retRd; if(retRd > 0){ Q_EMIT receivedMsg(&msg_in); //при приеме высылается сигнал } else{ qDebug()<<"Read Error = "<<retRd; //Q_EMIT () не считал } } if(cw->rflags & CI_WAIT_ER){ qDebug()<<"CI_WAIT_ER RECEIVE"; //canerrs_t errs; int retErr = CiErrsGetClear(cw->chan,&errs); qDebug()<<"Rx_Thrad retErr = "<<retErr; if(retErr >= 0){ if(errs.ewl){ qDebug()<<"EWL times Rx"<<errs.ewl; //общ f_err = true; qDebug()<<"Rx_Thread f_err = "<<f_err; mutex_event_tx.unlock(); } if(errs.boff){ qDebug()<<"BOFF times"<<errs.boff; //общ } if(errs.hwovr){ qDebug()<<"HOVR times"<<errs.hwovr; //rx } if(errs.swovr){ qDebug()<<"SOVR times"<<errs.swovr; //rx } if(errs.wtout){ qDebug()<<"WTOUT times Rx"<<errs.wtout; //tx f_err = true; qDebug()<<"Rx_Thread f_err = "<<f_err; mutex_event_tx.unlock(); } } } } else if(ret < 0){ qDebug()<<"Error CiWaitEvent = "<<ret; } else{ qDebug()<<"Time Out Rx"; Q_EMIT receiveTimeOut(); } qDebug()<<"receive thread go"; qDebug()<<"ret = "<<ret; } }
в другой поток (main), в котором происходит разбор посылки , а затем отображение данных на экране. C++ (Qt) void SuperVisor::initStartThreadRx() { qDebug()<<__FUNCTION__; threadRx = new ReceiveThread(&cw); connect(threadRx,SIGNAL(receivedMsg(canmsg_t*)),this,SLOT(parseFrame(canmsg_t*)),Qt::DirectConnection); connect(threadRx,SIGNAL(receivedMsg(canmsg_t*)),this,SLOT(strRxFrameData(canmsg_t*)),Qt::DirectConnection); connect(threadRx,SIGNAL(receiveTimeOut()),this,SIGNAL(timeOutReceive()),Qt::DirectConnection); connect(threadRx,SIGNAL(receiveStop()),this,SIGNAL(stopReceive()),Qt::DirectConnection); threadRx->startThread = true; threadRx->start(); } void SuperVisor::parseFrame(canmsg_t *msg) { qDebug()<<__FUNCTION__; if(msg != NULL){ _u16 frameIdAdr = (_u16)(msg->id & 0x0F); switch(frameIdAdr){ case BKT:{ _u16 frameIdCop = (_u16)(msg->id >> 7); qDebug()<<"cop BKT"; switch(frameIdCop){ case status_block:{ qDebug()<<"BKT status"; Q_EMIT receiveStatusBKT(msg); break; } case current_data:{ qDebug()<<"BKT current data"; Q_EMIT receiveDataBKT(msg); break; } default:{ break; } } break; } } } BKT_Widget * MainWindow::createWidgetBKT() { bktWidget = new BKT_Widget(); connect(superVisor,SIGNAL(receiveDataBKT(canmsg_t*)),bktWidget,SLOT(currentDataReceive(canmsg_t*))); connect(superVisor,SIGNAL(receiveStatusBKT(canmsg_t*)),bktWidget,SLOT(statusBlockReceive(canmsg_t*))); ... connect(bktWidget,SIGNAL(closeWidget()),this,SLOT(closeWidgetBKT())); return bktWidget; }
Но к сожалению, когда я закрываю окно виджета, то программа вылетает. C++ (Qt) void BKT_Widget::currentDataReceive(canmsg_t *msg) { canmsg_t *msgData = NULL; msgData = msg; //little-endian if(msgData != NULL){ float T1; qDebug()<<msgData; T1 = *(float*)(&(msgData->data[0])); //!!!!! Error T2 = *(float*)(&(msgData->data[4])); qDebug()<<"T1 = "<<T1; qDebug()<<"T2 = "<<T2; ui->leT1->setText(QVariant(T1).toString()); ui->leT2->setText(QVariant(T2).toString()); } }
Не могу понять с чем это может быть связанно???
Название: Re: потоки
Отправлено: Пантер от Апрель 13, 2015, 13:38
Запусти в дебаггере и посмотри на чем вылетает.
Название: Re: потоки
Отправлено: Johnik от Апрель 13, 2015, 13:47
Ошибки: 1. объекты в потоке вы создаете в стеке, в основной поток вы пуляете ссылки на эти объекты. 2. при подключении объектов (connect) из разных потоков используете: Qt::DirectConnection.
Название: Re: потоки
Отправлено: kuzulis от Апрель 13, 2015, 15:00
Гы, в этой же CAN-овской библиотеке есть каллбеки на Rx события, на которые можно подписаться с помощью CiSetCB() функции. Потоки вообще не нужны. Нужно просто проверить в каком контексте вызывается каллбек: в основном треде, или в треде, который создан внутри библиотеки. Если в другом - то просто добавить мьютексы на ресурс который изменяется (например на список готовых сообщений и пр.).
Я делал именно так (но я использовал TinyCAN устройство).
Здесь (http://marathon.ru/files/soft/man/CHAI-2.4.0-Programming-Guide.pdf)написано, что используется Phillips SJA1000 CAN контроллер, поэтому, IMHO, можно взять готовое API оттуда (может оно лучше), а не пользоваться API от "Марафона" :)
Название: Re: потоки
Отправлено: demaker от Апрель 14, 2015, 11:26
Извините не правильно написал. Когда я останавливаю поток. C++ (Qt) void SuperVisor::stopProcess() { if(thread_Rx != NULL){ thread_Rx->startThread = false; thread_Rx->quit(); thread_Rx->wait(); delete thread_Rx; thread_Rx = NULL; } CiStop(portInstall.number); CiClose(portInstall.number); fInst = false; }
То тогда возникает ошибка. Qt::DirectConnection я использую
Название: Re: потоки
Отправлено: demaker от Апрель 14, 2015, 11:32
По поводу Debug я указал где вылетает C++ (Qt) void BKT_Widget::currentDataReceive(canmsg_t *msg) { canmsg_t *msgData = NULL; msgData = msg; //little-endian if(msgData != NULL){ float T1; qDebug()<<msgData; T1 = *(float*)(&(msgData->data[0])); //!!!!! Error ВЫЛЕТАЕТ T2 = *(float*)(&(msgData->data[4])); qDebug()<<"T1 = "<<T1; qDebug()<<"T2 = "<<T2; ui->leT1->setText(QVariant(T1).toString()); ui->leT2->setText(QVariant(T2).toString()); } }
но не могу понять почему??? msgData не NULL но по этому указателю такое впечатление ничего не находится. Может надо в сигнало-слотовых соединениях передавать не указатель, а значение??? C++ (Qt) connect(threadRx,SIGNAL(receivedMsg(canmsg_t*)),this,SLOT(parseFrame(canmsg_t*)),Qt::DirectConnection); connect(threadRx,SIGNAL(receivedMsg(canmsg_t*)),this,SLOT(strRxFrameData(canmsg_t*)),Qt::DirectConnection);
Название: Re: потоки
Отправлено: demaker от Апрель 14, 2015, 16:27
Вроде избавился от бага. Сделал сигнало-слотовые соединения C++ (Qt) connect(threadRx,SIGNAL(receivedMsg(canmsg_t )),this,SLOT(parseFrame(canmsg_t )),Qt::DirectConnection); connect(threadRx,SIGNAL(receivedMsg(canmsg_t )),this,SLOT(strRxFrameData(canmsg_t )),Qt::DirectConnection);
C++ (Qt) BKT_Widget * MainWindow::createWidgetBKT() { bktWidget = new BKT_Widget(); connect(superVisor,SIGNAL(receiveDataBKT(canmsg_t)),bktWidget,SLOT(currentDataReceive(canmsg_t)),Qt::DirectConnection); connect(superVisor,SIGNAL(receiveStatusBKT(canmsg_t)),bktWidget,SLOT(statusBlockReceive(canmsg_t)),Qt::DirectConnection); ... connect(bktWidget,SIGNAL(closeWidget()),this,SLOT(closeWidgetBKT())); return bktWidget; }
Но после некоторой продолжительной работы программы вылезает ошибка в Debug internal error: pc 0xf in read in psymtab but not in symtab
скажите это может быть связано с переполнением буфера??? Скажите переменная передающаяся по значению через connect помещается в стек?
|