Solved QThread freezes whole app.
-
Today just started exploring QThreads, found it quite hard, especially when in pure C++ using <Thread.h> you can simply create Thread variable and assign any your function and you free to go.
I need simply run two my different functions which both have loops which going for about the minute.Both functions is from my MainWindow class.Here how my constructor looks:
MWindow::MWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MWindow) { ui->setupUi(this); thread1 = new QThread; this->moveToThread(thread1); connect(thread1, SIGNAL(started()), this, SLOT(myFunction1())); thread2 = new QThread; this->moveToThread(thread2); connect(thread2, SIGNAL(started()), this, SLOT(myFunction2())); }
And here is my push button slot:
void MWindow::on_runButton_clicked() { thread1->start(); thread2->start(); }
In output window it display warning: QObject::moveToThread: Widgets cannot be moved to a new thread
I tried with only one thread first, it working, i mean, whole application freezes while loop is not done, but result of myFunction1() is correct. And after that loop done, the program returns to work and everything fine.
In second case where is two threads(like in code examples above), app also freezes, but forever, none of two myFunctions is succeed.
I rly cant understand how to do simplest thing with QThreads - run two functions simultaneously. Please help.
-
Hi
You cannot have QWidgets in other thread than gui thread.
And you try to move mainwindow to new one. (this->moveToThread(thread1);
Hence the warning:While it possible to use QThread in other ways, i highly recommend using the worker approach.
https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
Note that the worker is based on QObject, not QWidget.
-
Hi! The whole process of executing heavy work in
Qt
is to remove it from the mainGUI
thread. So you have to create the worker class and implementmyFunction1()
andmyFunction2()
there, then connect it.Example:
QThread *thread1 = new QThread(); Worker *worker1 = new Worker(); worker->moveToThread(thread1); connect(thread1, &QThread::started, worker1, &Worker::myFunction1); connect(worker1, &Worker::mySignal1, this, &MWindow::mySlot1); connect(worker1, &Worker::finished, thread1, &QThread::quit); connect(worker1, &Worker::finished, worker1, &Worker::deleteLater); connect(thread1, &QThread::finished, thread1, &QThread::deleteLater); thread1->start(); QThread *thread2 = new QThread(); Worker *worker2 = new Worker(); worker2->moveToThread(thread2); connect(thread2, &QThread::started, worker2, &Worker::myFunction2); connect(worker2, &Worker::mySignal2, this, &MWindow::mySlot2); connect(worker2, &Worker::finished, thread2, &QThread::quit); connect(worker2, &Worker::finished, worker2, &Worker::deleteLater); connect(thread2, &QThread::finished, thread2, &QThread::deleteLater); thread2->start();
mySignalX
will emit the signal of the processing data from the thread to the GUI.mySlotX
will display the result. Alsofinished
signal should be emitted to quit from threads. You should call it when the loop is finished. -
I've already tried use my own custom class which inherit QThread and in that class reimplement void run(); function and it works. But the problem that(as i understand) the only way i can do multithreading - using that reimplemented run.
So as i understand - my custom class for multithreading can handle only one function(run();).
I need to make custom class for every different function?
-
Just now i tried simple <thread.h> class from std in my old VS. Damn it's bliss, 2 lines of code - 2 working threads, why the same cant be in Qt?
Tried same in Qt now, getting errors, code:
void MWindow::on_doButton_clicked() { std::thread firs(firstFunction); std::thread sec(secondFunction); }
Error: C3867: 'MWindow::firstFunction': non-standard syntax; use '&' to create a pointer to member
-
Well, qt is still c++, nothing stopping you from using part of the standart libary.
That said, fire and forget long functions than run a long time can be done (threaded) via QtConcurrent, thats in your case here, also pretty much a one liner.
void MWindow::on_doButton_clicked() { QtConcurrent::run(firstFunction); QtConcurrent::run(secondFunction); }
-
Hi! You used the wrong and old way of creating threads in
Qt
, that's why you must use 1 method in the run and create another worker for another method. I suggest you to use it right: How To Really, Truly Use QThreads; The Full Explanation. Using the new method of creating threads, you can create as many threads as you want from the single worker class.Also, you can use threads from standard C++:
#include <thread> std::thread firs(&MWindow::firstFunction); std::thread sec(&MWindow::secondFunction);
-
Also, you can use threads from standard C++:
#include <thread> std::thread firs(&MWindow::firstFunction); std::thread sec(&MWindow::secondFunction);
Well, i tried, and there is like 15 errors appear:
-
That said, fire and forget long functions than run a long time can be done (threaded) via QtConcurrent, thats in your case here, also pretty much a one liner.
void MWindow::on_doButton_clicked() { QtConcurrent::run(firstFunction); QtConcurrent::run(secondFunction); }
Well)) for that case, i got 199 errors when i added code as you suggested:
#include <QtConcurrent/QtConcurrent> void MWindow::on_doButton_clicked() { QtConcurrent::run(doProcess); QtConcurrent::run(doProcess2); }
-
I suggest you to use it right: How To Really, Truly Use QThreads; The Full Explanation. Using the new method of creating threads, you can create as many threads as you want from the single worker class.
Already tried that yesterday night. Everything seems perfect, no errors, but at the run time i got 4 alarms in Application Output about 3 signals in my Worker class and 1 slot. I didnt figure out whats wrong, but now i'm googling such issue
"QObject::connect: No such signal"
P.S. yes, my slot function in worker class in public slots: and signals: is just signal, they cant be in public.
-
@Engelard
Hi you have included QObject in worker class ?
class Worker : public QObject {
Q_OBJECT <<<<< -
@mrjj ah, forgot about that macro(never notice that, it always awtomaticly was created by QT)
Now i add it, and it adds me even more errors, but here is whole my code of worker header file:
#pragma once #include <QtCore> #include <QObject> #include <Windows.h> class TestThreads : public QObject { Q_OBJECT public: TestThreads(); static unsigned int addressNow; unsigned int addressMAX = 10; int myValue; bool scanDone = false; DWORD objID; public slots: void scanProcess(); signals: void addressFound(unsigned int addr); void addressValue(int val); void scanFinished(); };
And the result of adding that Q_OBJECT macro is this:
-
@Engelard
Well that is a normal case
Clean your build folder ( just delete all files)
and then run qmake.
Then rebuild all and it should be happy. -
@mrjj now there is new 3 errors)
-
@Engelard
Hi
Its "already defined" so check your .pro file
if you have the file(s) included twice for some reason. -
@mrjj nope, everything fine in there, all i have there is mentioned only once
-
@Engelard
hmm.
what files does class TestThread live it ?
Also did you give your signals a body in cpp for
void addressFound(unsigned int addr);
void addressValue(int val);
void scanFinished();
as it seems to complain about those.
(signals should not have a body) -
(signals should not have a body)
OMG, i didnt know, and as habbit i ofcource gave body(definitions) for every signal function.
Now its working, and threads working perfectly, thank you!
-
@Engelard
Yep its a true classic as normally u must always give a body or it complains about that.
but signals are just the signatures. -
@Engelard you need to properly tag people😉
Anyway QtConcurrent is its own modul, you‘ll need to add it in your pro file as such, as it is stated in the docuQT += concurrent
than it should work, now that you have removed the function body of the signal ☺️