Название: QThread
Отправлено: Firefox от Январь 10, 2017, 17:19
Здравствуйте. Столкнулась с проблемой следующей: хочу запихать в поток класс, в котором есть указатель на другой класс. Пихать все функции в один класс не охота. Думаю есть другое решение, которое я не знаю. Схема у меня следующая class A: public QObject { Q_OBJECT public: explicit A(QObject *parent,int par1, int par2) { cl_B=new B(); connect(cl_B,SIGNAL(...),this,SLOT(...)); }; private: B *cl_B; }; class B { Q_OBJECT .... }; class C: public QObject { Q_OBJECT public: explicit C(QObject *parent,int par1, int par2) { tr=new QThread(this); class1=new A(this,par1,par2); class1->moveToThred(tr); }; private: QThread *tr; A *class1; } В вывод выдается сообщение Cannot move QObjects with a parrent. Объясните, пожалуйста, как правильно надо.
Название: Re: QThread
Отправлено: Пантер от Январь 11, 2017, 08:54
1. Это точно полный код? Не вижу в нем проблемы, которая привела бы к выводу такого сообщения. 2. В конструкторе класса A задавай классу B парента this, иначе он не перенесется в поток.
Название: Re: QThread
Отправлено: Firefox от Январь 11, 2017, 11:12
Приведу код своих классов подробно. #ifndef TMK_BC_H #define TMK_BC_H
#include <QObject> #include <QSettings> #include <QTimer> #include <QDebug> #include <QTime>
#include "my_tmk/ltmk.h"
class tmk_bc: public QObject { Q_OBJECT public: explicit tmk_bc(); ~tmk_bc();
};
#endif // TMK_BC_H
//.cpp #include "tmk_bc.h"
tmk_bc::tmk_bc()
{
}
tmk_bc::~tmk_bc() {
}
#ifndef ADAPTER_TMK_H #define ADAPTER_TMK_H
#include <QObject> #include "tmk_bc.h"
class adapter_tmk : public QObject { Q_OBJECT public: explicit adapter_tmk(QObject *parent = 0,int par=0, int nTmk=0);
public slots: void process();
private: tmk_bc *fDrv;
};
#endif // ADAPTER_TMK_H //.cpp #include "adapter_tmk.h"
adapter_tmk::adapter_tmk(QObject *parent, int par, int nTmk) : QObject(parent) {
fDrv= new tmk_bc();
}
void adapter_tmk::process() { qDebug()<<__FUNCTION__<<this;
}
#ifndef GN_PP_H #define GN_PP_H
#include <QWidget> #include <QObject> #include <QDebug> #include <QDateTime> #include <QTextStream> #include <QThread> #include <QTextCodec> #include <QFrame> #include <QKeyEvent> #include <QTextEdit> #include <QLineEdit> #include <QMessageBox>
#include "tmk_bc.h" #include "my_tmk/adapter_tmk.h"
namespace Ui { class Widget; }
class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0,int par=0); ~Widget(); private: Ui::Widget *ui;
QThread *thread_bc1;
adapter_tmk *controller1;
};
#endif //.cpp #include "gn_pp.h" Widget::Widget(QWidget *parent, int par) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this);
thread_bc1= new QThread(this); controller1= new adapter_tmk(this,par,0); controller1->moveToThread(thread_bc1);
connect(thread_bc1,SIGNAL(started()),controller1,SLOT(process()));
//thread_bc1->start();
}
Widget::~Widget() { delete ui; if(thread_bc1->isRunning()) thread_bc1->terminate();
}
Посмотрите, пожалуйста.
Название: Re: QThread
Отправлено: Пантер от Январь 11, 2017, 11:19
Firefox, ты можешь минимальный компилябельный пример ошибки сделать? Вот реально, в твоём коде сейчас не хочется разбираться - много лишнего. Если приложишь пример без лишнего кода, я его скомпилю, поправлю и отвечу.
Название: Re: QThread
Отправлено: Firefox от Январь 11, 2017, 12:07
исправила предыдущий код. Все собирается, только в дебаг валится сообщение на функции moveToThread() QObject:moveToThread: Cannot move objects with a parent
Название: Re: QThread
Отправлено: Пантер от Январь 11, 2017, 12:12
controller1= new adapter_tmk(nullptr,par,0);
Название: Re: QThread
Отправлено: Firefox от Январь 11, 2017, 12:28
Спасибо. Без парента работает я это поняла, немогли бы вы мне объяснить для понимания. У меня была еще одна программа и там класс с конструктором, в котором QWidget *parent, помещается в поток и проблем нет. А QObject *parent приводит к таким проблемам?
Название: Re: QThread
Отправлено: Пантер от Январь 11, 2017, 12:38
QWidget вообще должен быть подальше от потоков. Просто запомни - если хочешь мувать в поток, забудь про парентов.
Название: Re: QThread
Отправлено: Firefox от Январь 11, 2017, 12:40
Спасибо :D
Название: Re: QThread
Отправлено: Firefox от Январь 16, 2017, 16:00
Возник еще один вопрос. При старте потока в функции я инициализирую некоторые данные, а далее по нажатию на кнопку стартует функция, которая работает циклически. Но по отжатию кнопки функцию надо прервать. Я создала сигнал, который иметируется при нажатии на кнопку и при отжатии. В слоте из потока при нажатии на кнопку выводится флаг и запускается функция. Если же кнопку отжали то в этом же слоте флаг устанавливается в 0. Внутри функции проверяется флаг и если он не 1 то делается return. Но проблема в том, что если функция уже запущено и крутится непрерывно то сигнала обработки нет, Тоесть в слот не попадает. Что можно сделать? думала что-то типа processEvents (), но не в могу понять как его в потоке использовать. EventFilter попробовала тоже самое.
Название: Re: QThread
Отправлено: Firefox от Январь 16, 2017, 17:13
Основной класс Widget::Widget(QWidget *parent, int par) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this);
thread_bc1= new QThread(this); controller1= new adapter_tmk(0,par,0);
controller1->moveToThread(thread_bc1); connect(thread_bc1,SIGNAL(started()),controller1,SLOT(process())); connect(controller1,SIGNAL(finished()),thread_bc1,SLOT(quit())); connect(controller1,SIGNAL(finished()),controller1,SLOT(deleteLater())); connect(thread_bc1,SIGNAL(finished()),thread_bc1,SLOT(deleteLater()));
connect(ui->send_pb,SIGNAL(clicked(bool)),controller1,SLOT(startObmen(bool)),Qt::AutoConnection);
thread_bc1->start();
}
Widget::~Widget() { delete ui; if(thread_bc1->isRunning()) thread_bc1->terminate();
}
поток #include "adapter_tmk.h"
adapter_tmk::adapter_tmk(QObject *parent, int par, int nTmk) : QObject() { tmk_N=nTmk; flag_send=false; flag_conf=false; Subaddress1=2; Subaddress1=3; connect(this, SIGNAL(sendSinhr_commandW(int,int,int,int,int,short)), this, SLOT(sendCommand_OU_10Format(int,int,int,int,int,short))); connect(this,SIGNAL(endSendFormat10(int,int)),this,SLOT(Slot_endSendFormat10(int,int))); connect(this, SIGNAL(sendData_7Format(int,int,QByteArray,int,int,int)), this, SLOT(sendData_OU_7Format(int,int,QByteArray,int,int,int))); connect(this,SIGNAL(endSendFormat7(int,int,int)),this,SLOT(Slot_endSendFormat7(int,int, int))); connect(this, SIGNAL(sendSinhr_command(int,int,int,int,bool,int)), this, SLOT(sendCommand_OU_9Format(int,int,int,int,bool,int)));
nTmk=0;
this->installEventFilter(this);
} adapter_tmk::~adapter_tmk() { }
void adapter_tmk::startSend(int Par_send,int lpi, int subaddr) {
if(flag_send==false) return;
switch(Par_send) { case 0: {
emit sendSinhr_commandW(Adress_ALL,BUS_A,CMD_SYNCHRONIZE_WITH_DATA_WORD,tmk_N,20,5);
}break; case 1: { QByteArray arr_send; arr_send.resize(32); emit sendData_7Format(Adress_ALL,subaddr,arr_send,lpi,tmk_N,20);///???
}break; case 2: { usleep(100*1000);
QByteArray arr_send; arr_send.resize(32); emit sendData_7Format(Adress_ALL,subaddr,arr_send,lpi,tmk_N,20);///??? count_line1++; if(count_line1==10 || count_line2==10) { emit sendSinhr_command(Adress_ALL,lpi,CMD_TRANSMIT_STATUS_WORD,tmk_N,false,20);
}
}break; //ERRORS case 1007: { startSend(0,BUS_A,Subaddress1);
}break; case 1010: { startSend(1,BUS_A,Subaddress2);
}break; } } void adapter_tmk::Slot_endSendFormat10(int rezult,int Lpi) { if(rezult==0) { startSend(1,BUS_A,Subaddress1); } else { startSend(1010,Lpi,Subaddress2); } } void adapter_tmk::Slot_endSendFormat7(int rezult, int Lpi, int wSubaddress) { if(rezult==0) { if(wSubaddress==Subaddress1) startSend(2,BUS_A,Subaddress2); else startSend(0,BUS_A,Subaddress1); } else { startSend(1007,Lpi,wSubaddress); } }
void adapter_tmk::startObmen(bool mean) { //СЮДА 2-ой РАЗ НЕ ЗАХОДИТ(Обработка события не работает) if(!flag_conf) return; if(mean) { flag_send=true; startSend(0,BUS_A, Subaddress1); } else { flag_send=false; }
} void adapter_tmk::process() { if(!tmk_configure(tmk_N)) { flag_conf=false;
} else { flag_conf=true; } }
bool adapter_tmk::tmk_configure(int tmkNumber) { return true; }
void adapter_tmk::sendData_OU_7Format(int tmkAddress,int wxSubaddress, QByteArray send_data, int busNumber, int tmkNumb,int time_wait) { emit endSendFormat7(0,lpi,wxSubaddress); } void adapter_tmk::sendCommand_OU_9Format(int tmkAddress,int busNumber, int command, int tmkNumb, bool rej_rab,int time_wait) { emit endSendFormat9(0, command,lpi,rej_rab); }
void adapter_tmk::sendCommand_OU_10Format(int tmkAddress,int busNumber, int command, int tmkNumb,int time_wait,short sd) { emit endSendFormat10(0,lpi); }
Название: Re: QThread
Отправлено: Firefox от Январь 18, 2017, 09:03
Проблема решилась заменой в connect (...,Qt:DirrctConnection)
Название: Re: QThread
Отправлено: Firefox от Январь 18, 2017, 13:07
Есть еще одна проблема. По кнопке стартует и завершается мой поток. Но внутри потока много раз в секунду с помощью сигналов /слотов и функций вызываемых внутри происходит обработка и завершение terminate () wait () потока происходит где-то в течение минуты что очень долго, потому как пока не завершится заново не запустить. Как то можно ускорить завершение?
Название: Re: QThread
Отправлено: Авварон от Январь 18, 2017, 13:19
Для начала, не спать. Долги операции периодически проверять флаг завершения. И да, возможно конкарент тут будет лучше. И да, терминейтить тред не стоит.
Название: Re: QThread
Отправлено: Firefox от Январь 18, 2017, 15:03
Оказалась проблема в том, что внутри класса который помещается в поток были вызовы функции, заменила на сигналы ( внутри одного потока) и все хорошо и быстро стало завершаться. Убрала терминэйт, как Вы и советуете. Спасибо
|