Not getting past emit command.
-
My Original approach was like you stated to move the worker object to a vanilla QThread. But then I ended up having other issues and compiling errors. People told me that the errors where caused because the object was not created in the 2nd thread where the worker object was moved to. I Will try it again and let you know what happens.
-
Ok. The above code was just an example of the issue I was facing in another bigger program. I Rewrote the code back to the way It was, where I try moving the objects to a vanilla QThread. I Get the same two errors as before.
On first run I usually get:
@QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0xb1fc20), parent's thread is QThread(0x15819a70), current thread is QThread(0xb30d50)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0xb1fc38), parent's thread is QThread(0x15819a70), current thread is QThread(0xb30d50)@on second run I sometimes get this error:
@Invalid parameter passed to C runtime function.
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 16e80d50. Receiver 'MainWindowWindow' (of type 'QWidgetWindow') was created in thread 154b9a70", file kernel\qcoreapplication.cpp, line 521
Invalid parameter passed to C runtime function.
QObject::killTimers: timers cannot be stopped from another thread
X:\MTEK\Programming\Contact Noise GUI\43\build-Contact_Noise-Desktop_Qt_5_3_MinGW_32bit-Debug\debug\Contact_Noise.exe exited with code 3@I Will post some of my code in the next couple of minutes.
-
I have omitted code that I think might be unnecessary.
@class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
bool TestActive;
bool ProcessEvents;
QEventLoop *EventLoopObj;QThread *TestThreadObj; TestClass *TestObj; RelayClass *RelayObj; ScopeClass *ScopeObj; MotorClass *MotorObj; explicit MainWindow(QWidget *parent = 0); ~MainWindow(); void Initialize(); void Uninitialize();
public slots:
void on_StartBtn_clicked();void SLOT_StopEventProcessing();
signals:
void SIGNAL_StartTest();};@
@MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
EventLoopObj = new QEventLoop(parent);TestThreadObj = new QThread(); TestObj = new TestClass(); RelayObj = new RelayClass(); ScopeObj = new ScopeClass(); MotorObj = new MotorClass();
}
MainWindow::~MainWindow()
{
EventLoopObj->deleteLater();MotorObj->deleteLater(); ScopeObj->deleteLater(); RelayObj->deleteLater(); TestThreadObj->deleteLater(); TestObj->deleteLater();
}
void MainWindow::Initialize()
{
//START THREAD OBJs
TestThreadObj->start();//MOVE OBJECTS TO THREADS TestObj->moveToThread(TestThreadObj); ScopeObj->moveToThread(TestThreadObj); MotorObj->moveToThread(TestThreadObj); RelayObj->moveToThread(TestThreadObj); //SET TEST OBJ TestObj->Initialize(); //SET RELAY OBJ RelayObj->setPort(ui->Relay_Com->text()); RelayObj->Initialize(); //SET SCOPE OBJ ScopeObj->Initialize(); //SET MOTOR OBJ MotorObj->SetPort(ui->Motor_Com->text()); //Merge with Initialize MotorObj->Initialize(); //CONNECT UI OBJ connect(this, SIGNAL(SIGNAL_StartTest()), TestObj,SLOT(StartTest())); connect(TestObj, SIGNAL(TestingDone()), this, SLOT(SLOT_StopEventProcessing())); //CONNECT RELAY OBJ connect(TestObj, SIGNAL(SIGNAL_AllRelaysOff()), RelayObj, SLOT(RelaysAllOff())); connect(TestObj, SIGNAL(SIGNAL_RelayOn(int)), RelayObj, SLOT(RelayOn(int))); //CONNECT SCOPE OBJ connect(TestObj, SIGNAL(SIGNAL_SCOPE_Initialize()), ScopeObj, SLOT(Initialize())); connect(TestObj, SIGNAL(SIGNAL_SCOPE_MeasureVavg()), ScopeObj, SLOT(TestVavg())); connect(TestObj, SIGNAL(SIGNAL_SCOPE_MeasureVpp()), ScopeObj, SLOT(TestVpp())); connect(TestObj, SIGNAL(SIGNAL_SCOPE_MeasureVrms()), ScopeObj, SLOT(TestVrms())); //CONNECT MOTOR OBJECT connect(TestObj, SIGNAL(SIGNAL_RunMotor()), MotorObj, SLOT(RunMotor())); TestActive = true; ProcessEvents =true;
}
void MainWindow::Uninitialize()
{
MotorObj->Uninitialize();ScopeObj->Uninitialize(); RelayObj->Uninitialize(); TestObj->Uninitialize(); TestThreadObj->quit();
}
void MainWindow::on_StartBtn_clicked()
{
Initialize();
emit SIGNAL_StartTest();
while(ProcessEvents == true)
{
EventLoopObj->processEvents();
}
Uninitialize();
}void MainWindow::SLOT_StopEventProcessing()
{
ProcessEvents = false;
}
@Inside the MotorObj and RelayObj there are QSerialPort variables.
QSerialPort* ComPort = new (QSerialPort);
From what I have read and understand this is where things go wrong.
The QSerialPorts Object seems to be running in the wrong thread.
I Have also tried to move the ComPort Objects contained in both MotorObj and RelayObj to the TestThread. When I do so The application Freezes when I click on the Start Button @MotorObj->ComPort->moveToThread(TestThreadObj);@ -
I have not studied the complete code sample yet. But does it help if you just create your QSerialPort object with the parent in the first place? QObject::moveToThread also moves all child objects, so that should work. If moving QSerialPort keeps given trouble, I suggest you only create it after the move from within the right thread.
-
Ok. I Will get back to you. Thanks for your help.
-
Looks like there was noting wrong with my initial approch by moving the objects to a Vanilla QThread. I Have managed to traced down the problem a bit more. I Think the warnings are a bit misleading. Below is the code for the RelayObj. If I comment out the "relays->write()" lines the errors disappear. Also If I create other objects in a similar way in the RelayClass like I do with QSerialPort I don't get any errors at all. Meaning it must be something to do with QSerialPort and how it behaves in a Threaded environment.
-
@#include "relayclass.h"
RelayClass::RelayClass(QObject *parent) : QObject(parent)
{
relays = new (QSerialPort);
}RelayClass::~RelayClass()
{
relays->deleteLater();
}void RelayClass::Initialize()
{
relays->setPortName(COM);if(relays->open(QIODevice::ReadWrite)) { relays->setBaudRate(QSerialPort::Baud9600); relays->setDataBits(QSerialPort::Data8); relays->setParity(QSerialPort::NoParity); relays->setStopBits(QSerialPort::OneStop); relays->setFlowControl(QSerialPort::NoFlowControl); }
}
void RelayClass::Uninitialize()
{
//relays->close();
}void RelayClass::RelaysAllOff()
{
relay_arr.clear();
relay_arr = "all_offx";
//relays->write(relay_arr); //Causes Error
relays->waitForBytesWritten(-1);
}void RelayClass::RelayOn(int Ch_on)
{
relay_arr.clear();
relay_arr.setNum(Ch_on);
relay_arr.prepend("ch");
relay_arr.append("_onx");
//relays->write(relay_arr); //Causes Error
relays->waitForBytesWritten(-1);
}void RelayClass::setPort(QString PORT)
{
COM = PORT;
}
@ -
@#ifndef RELAYCLASS_H
#define RELAYCLASS_H#include <QObject>
#include <QtSerialPort>
#include <QString>#include "waitclass.h"
class RelayClass : public QObject
{
Q_OBJECT
public:
QString COM;
QByteArray relay_arr;
QSerialPort *relays;WaitClass *WaitObj; explicit RelayClass(QObject *parent=0); ~RelayClass(); void Initialize(); void Uninitialize();
public slots:
void RelaysAllOff();
void RelayOn(int Ch_on);
void setPort(QString PORT);
};#endif // RELAYCLASS_H
@ -
Looks like this article may have the answer to my problems.
"LINK":http://stackoverflow.com/questions/23559610/how-to-setup-qserialport-on-a-separate-thread -
Ok. Problem solved.
I Moved the QSerialPort variables to my main thread and now use Signals and Slots to send data to them. I'm not an expert on this, and just quoting what I have read. QSerialPort already provides you non-blocking mechanism for your GUI application. When moving QSeerial Port to another thread this somehow interferes with the way objects communicate between one another and that is where the errors are coming from. If anyone has some extra opinions on this or knows how to move a QSerialPort object into a separate thread, please do share.