QObject: Cannot create children for a parent that is in a different thread: parent's thread:QThread(0x221f650), current thread:QThread(0x23a7950) - qt

I am trying to fetch data from device using QTCpSocket (telnet).
After a lot of struggle I felt I overcame one issue that was Qtimer:starttimer can not be started from other thread.
But,now I have came across another issue which is confusing me a lot.
I have gone through some post in internet but it's not helping me.
Please go through my code and let me know my mistake
fdu.cpp
#include "fdu.h"
#include "ui_fdu.h"
#include"fduprocess.h"
fdu::fdu(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::fdu)
{
ui->setupUi(this);
QThread *workerThread = new QThread;
fduprocess *worker = new fduprocess;
qDebug()<< "...goind to fduprocess........";
workerThread->start();
worker->_ReconnectionTimerInstance.setSingleShot(true);
worker->_ReconnectionTimerInstance.start(1000);
worker->_iStatusPollTimer = startTimer(500);
worker->moveToThread(workerThread);
connect(workerThread,SIGNAL(started()),worker,SLOT(tryit()));
connect(workerThread,SIGNAL(finished()),worker,SLOT(deleteLater()));
}
fdu::~fdu()
{
delete ui;
}
fduprocess.cpp
#include "fduprocess.h"
#include<QDebug>
#include<QThread>
fduprocess::fduprocess(QObject *parent) : QObject(parent)
{
}
void fduprocess::timerEvent(QTimerEvent *event)
{
if(event->timerId()== _iStatusPollTimer)
{
if(_ClientSocketInstance.state() == QAbstractSocket::ConnectedState)
{
_ClientSocketInstance.write("alarmstat\r\n"); //25
_ClientSocketInstance.write("selectedin\r\n"); // 4
_ClientSocketInstance.write("sigoutstat\r\n"); //13
_ClientSocketInstance.write("disablestat\r\n"); //5
_ClientSocketInstance.write("pwrstat\r\n"); //5
_ClientSocketInstance.write("siginstat\r\n");//5
}
}
}
void fduprocess::tryit()
{
qDebug()<< "...came inside tryit to tryit.........";
connect(&_ReconnectionTimerInstance,SIGNAL(timeout()), this, SLOT(when_ReconnectionTimer_timeout()));
qDebug()<< "...conencted to whentimeout.........";
connect(&_ClientSocketInstance,SIGNAL(connected()), this, SLOT(when_ClientSocketInstance_connected()));
connect(&_ClientSocketInstance,SIGNAL(disconnected()), this, SLOT(when_ClientSocketInstance_disconnected()));
connect(&_ClientSocketInstance,SIGNAL(readyRead()), this, SLOT(when_ClientSocketInstance_readyRead()));
connect(&_ClientSocketInstance,SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(when_ClientSocketInstance_error(QAbstractSocket::SocketError)));
_strIPAddress = "192.168.1.135";
_usiPort = 23;
qDebug()<< "...end tryit........";
}
void fduprocess::doOntimeout()
{
qDebug()<< "................";
}
void fduprocess::when_ReconnectionTimer_timeout()
{
qDebug()<<"Reconnecting..";
// qDebug()<< _ClientSocketInstance.children();
_ClientSocketInstance.connectToHost(_strIPAddress, _usiPort);
}
void fduprocess::when_ClientSocketInstance_connected()
{ qDebug()<<"Connected......";
_ClientSocketInstance.write("endrun_1");
_ClientSocketInstance.flush();
_ClientSocketInstance.write("\n");
_ClientSocketInstance.write("\n");
_ClientSocketInstance.write("\n");
_ClientSocketInstance.flush();
}
void fduprocess::when_ClientSocketInstance_disconnected()
{
qDebug()<<"Disconnected";
_ReconnectionTimerInstance.start();
}
void fduprocess::when_ClientSocketInstance_readyRead()
{
QByteArray get = _ClientSocketInstance.readLine();
qDebug() << get ;
}
void fduprocess::when_ClientSocketInstance_error(QAbstractSocket::SocketError error)
{
}
Any other feedback regarding any other code smells will be highly welcomed
Please ignore my indentation and naming conventions,since I am in my learning curve.
Here is the console output :
...goind to fduprocess........
...came inside tryit to tryit.........
...conencted to whentimeout.........
...end tryit........
Reconnecting..
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x609250), parent's thread is QThread(0x221f650), current thread is QThread(0x23a7950)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x609250), parent's thread is QThread(0x221f650), current thread is QThread(0x23a7950)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x609250), parent's thread is QThread(0x221f650), current thread is QThread(0x23a7950)

When you create worker, the object and all its members are created in the main thread. Then, you move worker to its own thread, which moves all its children QObjects. All slots in worker will now be executed on this new thread.
From fduprocess constructor, it looks like you don't give a parent to your socket (_ClientSocketInstance). That means the socket is not moved to the same thread as the worker but stays in the main thread, which gives this warning when you use it from a slot. If you pass this to _ClientSocketInstance constructor to make it a child of worker, it will automatically be moved to the same thread as worker and the warning should disappear.

Related

QT-How to utilize QWidget with QThread?

I'm making some GUI through QT.
I almost complete my work but I have a hard time dealing with Qthread.
My goal is to measure the position of the motor (it moves) and display it on the Qtextbrowser while working another function in the main thread. When I wrote codes like below, people said I can't use QTextBrowser(Qwidget) directly in the thread, so I'm searching how to return location value to the main thread. Can you do me a favor?
MDCE is a class in another header and the codes I attach are some parts of my first code.
void MotorPort::StartThread(MDCE* com, QTextBrowser* browser)
{
thread1 = QThread::create(std::bind(&MotorPort::MeasureLocation,this,com,browser));
thread1 -> start();
}
void MotorPort::MeasureLocation(MDCE* com, QTextBrowser* browser)
{
double location;
while(1)
{
location = CurrentLocation(com); \\return current position value
browser->setText(QString::number(location));
if (QThread::currentThread()->isInterruptionRequested()) return ;
}
}
void MotorPort::stopMeasure()
{
thread1->requestInterruption();
if (!thread1->wait(3000))
{
thread1->terminate();
thread1->wait();
}
thread1 = nullptr;
}
You should use the Qt signal/slot mechanism for iter-thread notification such as this. Firstly change your MotorPort class definition to declare a signal location_changed...
class MotorPort: public QObject {
Q_OBJECT;
signals:
void location_changed(QString location);
...
}
Now, rather than MotorPort::MeasureLocation invoking QTextBrowser::setText directly it should emit the location_changed signal...
void MotorPort::MeasureLocation (MDCE *com, QTextBrowser *browser)
{
while (true) {
double location = CurrentLocation(com);
/*
* Emit signal to notify of location update.
*/
emit location_changed(QString::number(location));
if (QThread::currentThread()->isInterruptionRequested())
return ;
}
}
Finally, update MotorPort::StartThread to connect the signal to the browser's setText slot...
void MotorPort::StartThread (MDCE *com, QTextBrowser *browser)
{
connect(this, &MotorPort::location_changed, browser, &QTextBrowser::setText);
thread1 = QThread::create(std::bind(&MotorPort::MeasureLocation, this, com, browser));
thread1->start();
}

QObject: Cannot create children for a parent that is in a different thread & QProcess [duplicate]

I am using Qt 4.6.0 (32 bit) under Windows 7 Ultimate. Consider the following QThread:
Interface
class ResultThread : public QThread
{
Q_OBJECT
QString _post_data;
QNetworkAccessManager _net_acc_mgr;
signals:
void onFinished(QNetworkReply* net_reply);
private slots:
void onReplyFinished(QNetworkReply* net_reply);
public:
ResultThread();
void run();
void setPostData(const QString& post_data);
};
Implementation
ResultThread::ResultThread() : _net_acc_mgr(this)
{
connect(&_net_acc_mgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(onReplyFinished(QNetworkReply*)));
}
void ResultThread::onReplyFinished(QNetworkReply* net_reply)
{
emit onFinished(net_reply);
}
void ResultThread::setPostData(const QString& post_data)
{
_post_data = post_data;
}
void ResultThread::run()
{
_net_acc_mgr.post(QNetworkRequest(QUrl("http://[omitted]")),
QByteArray(_post_data.toStdString().c_str()));
}
Whenever _net_acc_mgr.post() is executed in ResultThread::run(), I got the following Application Output in Qt Creator:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0x22fe58), parent's thread is QThread(0x9284190), current thread is ResultThread(0x22fe48)
What does this mean? How to solve it?
The run() member function is executed in a different thread, rather than the thread where QNetworkRequestManager object was created.
This kind of different-thread problems happen all the time with Qt when you use multiple threads. The canonical way to solve this problem is to use signals and slots.
Create a slot in the object where QNetworkRequestManager belongs to, create a signal in ResultThread and connect both of the somewhere, the constructor of ResultThread would be a good place.
The code which is currently in ResultThread::run() goes to the new slot, and is replaced by a emit(yourSignal()). If necessary send a pointer to your ResultThread as a parameter with your emit function to gain access to member functions/variables.
I received this error message when I forgot to set the QNetworkRequestManager's parent.
nam = new QNetworkAccessManager(this);

Exit QThread when GUI Application exits

I have the following worker class:
class MediaWorker : public QObject
{
Q_OBJECT
public:
explicit MediaWorker(QObject *parent = 0);
~MediaWorker();
void Exit();
signals:
void Finished();
public slots:
void OnExecuteProcess();
};
In MediaWorker.cpp
void MediaWorker::Exit()
{
emit Finished();
}
void MediaWorker::OnExecuteProcess()
{
qDebug() << "Worker Thread: " << QThread::currentThreadId();
}
In my MainWindow I do the following:
this->threadMediaWorker = new QThread();
this->mediaWorker = new MediaWorker();
this->timerMediaWorker = new QTimer();
this->timerMediaWorker->setInterval(1000);
this->timerMediaWorker->moveToThread(this->threadMediaWorker);
this->mediaWorker->moveToThread(this->threadMediaWorker);
connect(this->threadMediaWorker, SIGNAL(started()), this->timerMediaWorker, SLOT(start()));
connect(this->timerMediaWorker, &QTimer::timeout, this->mediaWorker, &MediaWorker::OnExecuteProcess);
connect(this->mediaWorker, &MediaWorker::Finished, this->threadMediaWorker, &QThread::quit);
connect(this->mediaWorker, &MediaWorker::Finished, this->mediaWorker, &MediaWorker::deleteLater);
connect(this->threadMediaWorker, &QThread::finished, this->mediaWorker, &QThread::deleteLater);
this->threadMediaWorker->start();
The threading is working properly. When I close the application I terminate the thread in the destructor:
MainWindow::~MainWindow()
{
delete ui;
this->mediaWorker->Exit();
}
so Exit() emits the Finished signal which will hopefully delete the qthread and mediaworker class.
My question is if this is the proper way of terminating both the thread and media worker class?
My question is what is the proper way of terminating both the
worker thread and media worker class?
You can just ensure that the 'media' object gets deleted while the main window gets destructed by using either QScopedPointer or std::unique_ptr.
class MainWindow : public QMainWindow {
/// ...
QThread m_workerThread;
QScopedPointer<MediaWorker> m_pMediaObject;
/// ...
};
void MainWindows::init()
{
// ... other initialization skipped ...
// for dynamic allocation of the object and keeping the track of it
m_mediaObject.reset(new MediaWorker());
m_workerThread.moveToThread(m_mediaObject.data());
}
void MainWindow::stopWorker()
{
if (m_workerThread.isRunning())
{
m_workerThread.quit(); // commands Qt thread to quit its loop
// wait till the thread actually quits
m_workerThread.wait(); // possible to specify milliseconds but
// whether or not to limit the wait is
// another question
}
}
If the worker thread used for updating the UI it makes sense to attempt to stop the worker thread before the UI objects released in
void MainWindow::closeEvent(QCloseEvent *)
{
stopWorker();
}
But there is a chance that the main window never gets closeEvent() called before the destruction so we should handle that:
MainWindow::~MainWindow()
{
stopWorker();
// it also destroys m_mediaObject
}

Why does my asynchronous QProgressBar render black?

I want a QProgressBar to show in a modal dialog and update asynchronously as another thread does work.
struct ProgressThread : public QThread
{
QDialog m_dialog;
QProgressBar * m_bar;
ProgressThread (QWidget * parent, int range)
: m_dialog (parent)
, m_bar (new QProgressBar ())
{
auto l = new QGridLayout (& m_dialog);
l -> addWidget (m_bar, 0, 0);
m_bar -> setRange (0, range);
}
void run () override
{
m_dialog .exec ();
}
};
ProgressThread thread (this, range);
thread .start ();
int num = 0;
for (each job)
{
do_some_work ();
thread .m_bar -> setValue (++ num);
}
thread .m_dialog .accept ();
thread .wait (1000);
thread .quit ();
It basically works except the progress bar renders as a black block. Why is this happening?
This is a design problem. Neither Qt nor most of other UI frameworks designed to run multiple threads for UI though this innovative approach may take place. Most of UI classes just expect to be running on same main thread. Qt can never guarantee that it works the way you are attempting: running the dialog exec() on a worker thread.
How to convert the source code you have to Qt way? Your source code encapsulates QDialog and QProgressBar immediately in thread instance which is maybe not incorrect yet until you do moveToThread(uiObject). But still, it shows the wrong design. You can just follow normal pattern for the worker thread interacting with UI:
// make sure to place it in the header file
class ProgressThread : public QDialog
{
Q_OBJECT
public:
// if you ever need to access that from outside
// QProgressBar* bar() {return m_bar;}
public slots:
void moveProgress(int);
private:
QProgressBar* m_bar;
};
class ProgressThread : public QThread
{
Q_OBJECT
public:
// add methods
signals:
moveProgress(int);
};
You need to connect the slot to signal:
// for interthread communication a queued connection will be automatical
// figure out how to get the pointer to that dialog class (dialogPtr)
QObject::connect(&thread, SIGNAL(moveProgress(int)), dialogPtr(), SLOT(moveProgress(int));
And from the thread code you emit the signal to advance the progress bar on UI thread:
emit moveProgress(value);
The similar question/answers: QProgressBar not showing progress?
And make sure that UI thread starts from the application main() function!

Using POSIX threads in Qt Widget App

I'm relatively new to both Qt and pthreads, but I'm trying to use a pthread to work in the background of basic test app I'm making. I'm aware of the Qt Frameworks own threading framework - but there's a lot of complaint surrounding it so I'd like to use pthread if possible. The code is as below
#include "drawwindow.h"
#include "ui_drawwindow.h"
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include "QThread"
pthread_t th1;
DrawWindow::DrawWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::DrawWindow)
{
ui->setupUi(this);
}
DrawWindow::~DrawWindow()
{
delete ui;
}
void DrawWindow::on_pushButton_clicked()
{
pthread_create(&th1, NULL, &DrawWindow::alter_text, NULL);
}
void DrawWindow::alter_text()
{
while(1)
{
ui->pushButton->setText("1");
QThread::sleep(1);
ui->pushButton->setText("one");
QThread::sleep(1);
}
}
With the header
#ifndef DRAWWINDOW_H
#define DRAWWINDOW_H
#include <QMainWindow>
namespace Ui {
class DrawWindow;
}
class DrawWindow : public QMainWindow
{
Q_OBJECT
public:
explicit DrawWindow(QWidget *parent = 0);
~DrawWindow();
void alter_text();
private slots:
void on_pushButton_clicked();
private:
Ui::DrawWindow *ui;
};
#endif // DRAWWINDOW_H
And I'm getting the error
error: cannot convert 'void (DrawWindow::*)()' to 'void* (*)(void*)' for argument '3' to 'int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)'
pthread_create(&th1, NULL, &DrawWindow::alter_text, NULL);
^
Does anyone know what is wrong?
TL;DR: The way you're using pthreads is precisely the discouraged way of using QThread. Just because you use a different api doesn't mean that what you're doing is OK.
There's absolutely no problem with either QThread or std::thread. Forget about pthreads: they are not portable, their API is C and thus abhorrent from a C++ programmer's perspective, and you'll be making your life miserable for no reason by sticking to pthreads.
Your real issue is that you've not understood the concerns with QThread. There are two:
Neither QThread nor std::thread are destructible at all times. Good C++ design mandates that classes are destructible at any time.
You cannot destruct a running QThread nor std::thread. You must first ensure that it's stopped, by calling, respectively QThread::wait() or std::thread::join(). It wouldn't have been a big stretch to have their destructors do that, and also stop the event loop in case of QThread.
Way too often, people use QThread by reimplementing the run method, or they use std::thread by running a functor on it. This is, of course, precisely how you use pthreads: you run some function in a dedicated thread. The way you're using pthreads is just as bad as the discouraged way of using QThread!
There are many ways of doing multithreading in Qt, and you should understand the pros and cons of each of them.
Thus, how do you do threading in C++/Qt?
First, keep in mind that threads are expensive resources, and you should ideally have no more threads in your application than the number of available CPU cores. There are some situations when you're forced to have more threads, but we'll discuss when it's the case.
Use a QThread without subclassing it. The default implementation of run() simply spins an event loop that allows the objects to run their timers and receive events and queued slot calls. Start the thread, then move some QObject instances to it. The instances will run in that thread, and can do whatever work they need done, away from the main thread. Of course, everything that the objects do should be short, run-to-completion code that doesn't block the thread.
The downside of this method is that you're unlikely to exploit all the cores in the system, as the number of threads is fixed. For any given system, you might have exactly as many as needed, but more likely you'll have too few or too many. You also have no control over how busy the threads are. Ideally, they should all be "equally" busy.
Use QtConcurrent::run. This is similar to Apple's GCD. There is a global QThreadPool. When you run a functor, one thread from the pool will be woken up and will execute the functor. The number of threads in the pool is limited to the number of cores available on the system. Using more threads than that will decrease performance.
The functors you pass to run will do self-contained tasks that would otherwise block the GUI leading to usability problems. For example, use it to load or save an image, perform a chunk of computations, etc.
Suppose you wish to have a responsible GUI that loads a multitude of images. A Loader class could do the job without blocking the GUI.
class Loader : public QObject {
Q_OBJECT
public:
Q_SIGNAL void hasImage(const QImage &, const QString & path);
explicit Loader(const QStringList & imagePaths, QObject * parent = 0) :
QObject(parent) {
QtConcurrent::map(imagePaths, [this](const QString & path){
QImage image;
image.load(path);
emit hasImage(image, path);
});
}
};
If you wish to run a short-lived QObject in a thread from the thread pool, the functor can spin the event loop as follows:
auto foo = QSharedPointer<Object>(new Object); // Object inherits QObject
foo->moveToThread(0); // prepares the object to be moved to any thread
QtConcurrent::run([foo]{
foo->moveToThread(QThread::currentThread());
QEventLoop loop;
QObject::connect(foo, &Object::finished, &loop, &QEventLoop::quit);
loop.exec();
});
This should only be done when the object is not expected to take long to finish what it's doing. It should not use timers, for example, since as long as the object is not done, it occupies an entire thread from the pool.
Use a dedicated thread to run a functor or a method. The difference between QThread and std::thread is mostly in that std::thread lets you use functors, whereas QThread requires subclassing. The pthread API is similar to std::thread, except of course that it is C and is awfully unsafe compared to the C++ APIs.
// QThread
int main() {
class MyThread : public QThread {
void run() { qDebug() << "Hello from other thread"; }
} thread;
thread.start();
thread.wait();
return 0;
}
// std::thread
int main() {
// C++98
class Functor {
void operator()() { qDebug() << "Hello from another thread"; }
} functor;
std::thread thread98(functor);
thread98.join();
// C++11
std::thread thread11([]{ qDebug() << "Hello from another thread"; });
thread11.join();
return 0;
}
// pthread
extern "C" void* functor(void*) { qDebug() << "Hello from another thread"; }
int main()
{
pthread_t thread;
pthread_create(&thread, NULL, &functor, NULL);
void * result;
pthread_join(thread, &result);
return 0;
}
So, what is this good for? Sometimes, you have no choice but to use a blocking API. Most database drivers, for example, have blocking-only APIs. They expose no way for your code to get notified when a query has been finished. The only way to use them is to run a blocking query function/method that doesn't return until the query is done. Suppose now that you're using a database in a GUI application that you wish to remain responsive. If you're running the queries from the main thread, the GUI will block each time the database query run. Given long-running queries, a congested network, a dev server with a flaky cable that makes the TCP perform on par with sneakernet... you're facing huge usability issues.
Thus, you can't but have to run the database connection on, and execute the database queries on a dedicated thread that can get blocked as much as necessary.
Even then, it might still be helpful to use some QObject on the thread, and spin an event loop, since this will allow you to easily queue the database requests without having to write your own thread-safe queue. Qt's event loop already implements a nice, thread-safe event queue so you might as well use it. For example, with a note that Qt's SQL module can be used from one thread only - thus you can't prepare QSQLQuery in the main thread :(
Note that this example is very simplistic, you'd likely want to provide thread-safe way of iterating the query results, instead of pushing the entire query's worth of data at once.
class DBWorker : public QObject {
Q_OBJECT
QScopedPointer<QSqlDatabase> m_db;
QScopedPointer<QSqlQuery> m_qBooks, m_query2;
Q_SLOT void init() {
m_db.reset(new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE")));
m_db->setDatabaseName(":memory:");
if (!m_db->open()) { emit openFailed(); return; }
m_qBooks.reset(new QSqlQuery(*m_db));
m_qBooks->prepare("SELECT * FROM Books");
m_qCars.reset(new QSqlQuery(*m_db));
m_qCars->prepare("SELECT * FROM Cars");
}
QList<QVariantList> read(QSqlQuery * query) {
QList<QVariantList> result;
result.reserve(query->size());
while (query->next()) {
QVariantList row;
auto record = query->record();
row.reserve(record.count());
for (int i = 0; i < recourd.count(); ++i)
row << query->value(i);
result << row;
}
return result;
}
public:
typedef QList<QVariantList> Books, Cars;
DBWorker(QObject * parent = 0) : QObject(parent) {
QObject src;
connect(&src, &QObject::destroyed, this, &DBWorker::init, Qt::QueuedConnection);
m_db.moveToThread(0
}
Q_SIGNAL void openFailed();
Q_SIGNAL void gotBooks(const DBWorker::Books &);
Q_SIGNAL void gotCars(const DBWorker::Cars &);
Q_SLOT void getBooks() {
Q_ASSERT(QThread::currentThread() == thread());
m_qBooks->exec();
emit gotBooks(read(m_qBooks));
}
Q_SLOT void getCars() {
Q_ASSERT(QThread::currentThread() == thread());
m_qCars->exec();
emit gotCars(read(m_qCars));
}
};
Q_REGISTER_METATYPE(DBWorker::Books);
Q_REGISTER_METATYPE(DBWorker::Cars);
// True C++ RAII thread.
Thread : public QThread { using QThread::run; public: ~Thread() { quit(); wait(); } };
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
Thread thread;
DBWorker worker;
worker.moveToThread(&thread);
QObject::connect(&worker, &DBWorker::gotCars, [](const DBWorker::Cars & cars){
qDebug() << "got cars:" << cars;
qApp->quit();
});
thread.start();
...
QMetaObject::invokeMethod(&worker, "getBooks"); // safely invoke `getBooks`
return app.exec();
}
Change void DrawWindow::alter_text() to void* DrawWindow::alter_text(void*) and return pthread_exit(NULL);.

Resources