Russian Qt Forum
Ноябрь 24, 2024, 10:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: потоки  (Прочитано 4120 раз)
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« : Апрель 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());
   }
}
 
 

Не могу понять с чем это может быть связанно???



Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Апрель 13, 2015, 13:38 »

Запусти в дебаггере и посмотри на чем вылетает.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Johnik
Крякер
****
Online Online

Сообщений: 339


Просмотр профиля
« Ответ #2 : Апрель 13, 2015, 13:47 »

Ошибки:
1. объекты в потоке вы создаете в стеке, в основной поток вы пуляете ссылки на эти объекты.
2. при подключении объектов (connect) из разных потоков используете: Qt::DirectConnection.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #3 : Апрель 13, 2015, 15:00 »

Гы, в этой же CAN-овской библиотеке есть каллбеки на Rx события, на которые можно подписаться с помощью CiSetCB() функции.
Потоки вообще не нужны. Нужно просто проверить в каком контексте вызывается каллбек: в основном треде, или в треде, который создан внутри библиотеки.
Если в другом - то просто добавить мьютексы на ресурс который изменяется (например на список готовых сообщений и пр.).

Я делал именно так (но я использовал TinyCAN устройство).

Здесь написано, что используется Phillips SJA1000 CAN контроллер, поэтому,
IMHO, можно взять готовое API оттуда (может оно лучше), а не пользоваться API от "Марафона"  Улыбающийся
« Последнее редактирование: Апрель 13, 2015, 15:11 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #4 : Апрель 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
я использую
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #5 : Апрель 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);
 

Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #6 : Апрель 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 помещается  в стек?
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.2 секунд. Запросов: 23.