QThread with Android
-
Hi Guys
I have written a code to demonstrate QThread on Android mobile.header: #ifndef FUNCTIONCLASS_H #define FUNCTIONCLASS_H #include <QObject> #include<QThread> #include<QDebug> class FunctionClass : public QObject { Q_OBJECT public: FunctionClass(); signals: void signalofmainclass(); public slots: void workdone(); }; #endif // FUNCTIONCLASS_H
.CPP:
#include "functionclass.h" FunctionClass::FunctionClass() { } void FunctionClass::workdone() { qDebug()<<"In workdone class"; // qDebug()<<"FUNCTION CALLED:"<<Q_FUNC_INFO<<endl; // qDebug()<<"storedatathread:"<<QThread::currentThreadId()<<endl; QThread::sleep(10); qDebug()<<"*******************8SUCCESS**************************"; emit signalofmainclass(); }
///////////////////////////////////////////////////////////////////////////////////////////
header:#ifndef MULTICLASS_H #define MULTICLASS_H #include <QObject> #include <functionclass.h> class Multiclass : public QThread { Q_OBJECT public: explicit Multiclass(); signals: void dicomStoreComplete(); protected : void run() override; private: FunctionClass *funt; public slots: }; #endif // MULTICLASS_H
.cpp: #include "multiclass.h" Multiclass::Multiclass() { } void Multiclass::run() { funt = new FunctionClass; qDebug()<<"IN multiclass"; qDebug()<<"WORKER THREAD ID:"<<QThread::currentThreadId()<<endl; connect(funt,SIGNAL(signalofmainclass()),this,SIGNAL(dicomStoreComplete())); funt->workdone(); }
///////////////////////////////////////////////////////////////////////////////////////////
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <functionclass.h> #include <QQmlContext> #include<QDebug> #include <multiclass.h> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); qDebug()<<"MAIN THREAD ID:"<<QThread::currentThreadId()<<endl; FunctionClass DB; Multiclass *task=new Multiclass; QQmlApplicationEngine engine; QQmlContext *context =engine.rootContext(); context->setContextProperty("db",task); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
////////////////////////////////////////////////////////////////////
My expectation is when i click 2 times on my screen this statement should execute 2 times with a duration of 10 sec
But it is not executing twice it is just executing once.
qDebug()<<"8SUCCESS*****";**
My QML FILE is:import QtQuick 2.6 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Rectangle {id:xyz anchors.fill:parent color:"RED" MouseArea { anchors.fill:parent onClicked:{db.start();xyz.color="GREEN";} } } Connections { target:db onDicomStoreComplete:{console.log("lunch");} } }
What is missing in my code?
-
@ashajg said in QThread with Android:
besides a bunch of other stuff,donedo not use Thread::sleep, and it should work.QThread::sleep(10);
edit that should have been don't instead of done
-
try
void FunctionClass::workdone() { qDebug()<<"In workdone class"; QTime time; time.start(); while(time.elapsed() < 10000) {} qDebug()<<"*******************8SUCCESS**************************"; emit signalofmainclass(); }
You're not meant to call QThread::sleep, in Qt. All kinds of strange things happen, when one does it.
actually what you should rather do is something like this:
void FunctionClass::workdone() { qDebug()<<"In workdone class"; QTimer::singleShot(10000, this, [=]()->void{ qDebug()<<"*******************8SUCCESS**************************"; emit signalofmainclass(); }); }
-
@ashajg
looking a bit closer at your code.You have only one instance of your "multiclass" where you call start on, start calls automatically run, you can't simply call again start when the thread is already running!
They way you created this makes this currently a one time use only instance/function -
@ashajg
I think subclassing QThread is for your case the wrong solution. It is in fact the wrong one for most cases.
I would suggest reading through this block post to get an Idea how QThread is supposed to be used most of the time.
https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/In your code example I would actually go to QtConcurrent.
You could mark a function Q_INVOKABLE so you can access it from QML and start a ne QtConCurrent function.
For example//.h Q_INVOKABLE void doInParallel(); //actual function void myClass:: doInParallel(){ QtConcurrent::run([=]()->void{ auto funt = new FunctionClass; qDebug()<<"IN multiclass"; qDebug()<<"WORKER THREAD ID:"<<QThread::currentThreadId()<<endl; connect(funt,SIGNAL(signalofmainclass()),this,SIGNAL(dicomStoreComplete())); connect(func, &FunctionClass:: signalofmainclass, func, & FunctionClass::deleteLater());//Your previously leaked the function instance, this fixes that. funt->workdone(); }); }
this is untested of course, just food for thought.
-
here a working example
//multiclass #ifndef MULTICLASS_H #define MULTICLASS_H #include <QObject> class Multiclass : public QObject { Q_OBJECT public: explicit Multiclass(QObject *parent = nullptr); Q_INVOKABLE void doInParallel(); signals: void working(qint64 id, int index); void workDone(); }; #endif // MULTICLASS_H //cpp #include "multiclass.h" #include <QtConcurrent> #include <QDebug> Multiclass::Multiclass(QObject *parent) : QObject(parent) { connect(this, &Multiclass::working, this, [=](qint64 id, int index){ qDebug() << "Thread:" << id << "index" << index; }); } void Multiclass::doInParallel() { QtConcurrent::run([=]()->void{ qDebug()<<"doParallel"; qDebug()<<"WORKER THREAD ID:"<< QThread::currentThreadId()<<endl; for(int i(0); i < 0xFFFF; i++){ if(i % 1000 == 0) emit working(reinterpret_cast<qint64>(QThread::currentThread()), i); qDebug() << sqrt(i); } emit workDone(); }); }
//main.cpp #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "multiclass.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); Multiclass *backEnd = new Multiclass; QQmlApplicationEngine engine; QQmlContext *context =engine.rootContext(); context->setContextProperty("BackEnd",backEnd); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
//main.qml import QtQuick 2.6 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Rectangle { id:xyz anchors.fill:parent color:"RED" MouseArea { anchors.fill:parent onClicked:{ BackEnd.doInParallel(); xyz.color ="red"; } } } Connections { target:BackEnd onWorking: console.log(id, index); onWorkDone: { xyz.color ="green"; console.log("Work done"); } } }