QT thread not syncing
-
I am working on a project for passing argument and return the values in between thread. So far I have tried:
mainwindow.cpp (slightly updated)
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // The thread and the worker are created in the constructor so it is always safe to delete them. thread = new QThread(); worker = new Worker(); worker->moveToThread(thread); connect(worker, SIGNAL(valueChanged(QString)), this, SLOT(addNewImage(QString))); connect(worker, SIGNAL(workRequested()), thread, SLOT(start())); // connect(thread, SIGNAL(started()), worker, SLOT(doWork(int))); connect(this, SIGNAL(requestUpdate(int)), worker, SLOT(doWork(int))); connect(worker, SIGNAL(finished()), thread, SLOT(quit()), Qt::DirectConnection); } MainWindow::~MainWindow() { worker->abort(); thread->wait(); qDebug()<<"Deleting thread and worker in Thread "<<this->QObject::thread()->currentThreadId(); delete thread; delete worker; delete ui; } void MainWindow::on_startButton_clicked() { int i=0; for(i=0;i<5;i++) // Run 5 times { // To avoid having two threads running simultaneously, the previous thread is aborted. worker->abort(); thread->wait(); // If the thread is not running, this will immediately return. int enc = 5; //worker->requestWork(); emit requestUpdate(enc); } } void MainWindow::addNewImage(QString enc) { qDebug(qUtf8Printable(enc)); }
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QThread> #include "worker.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; /** * @brief Thread object which will let us manipulate the running thread */ QThread *thread; /** * @brief Object which contains methods that should be runned in another thread */ Worker *worker; private slots: void on_startButton_clicked(); public slots: void addNewImage(QString enc); signals: void requestUpdate(int initial); }; #endif // MAINWINDOW_H
and worker.cpp
#include "worker.h" #include <QTimer> #include <QEventLoop> #include <QThread> #include <QDebug> Worker::Worker(QObject *parent) : QObject(parent) { _working =false; _abort = false; } void Worker::requestWork() { mutex.lock(); _working = true; _abort = false; qDebug()<<"Request worker start in Thread "<<thread()->currentThreadId(); mutex.unlock(); emit workRequested(); } void Worker::abort() { mutex.lock(); if (_working) { _abort = true; qDebug()<<"Request worker aborting in Thread "<<thread()->currentThreadId(); } mutex.unlock(); } void Worker::doWork(int initial) { qDebug()<<"Starting worker process in Thread "<<thread()->currentThreadId(); // Checks if the process should be aborted mutex.lock(); bool abort = _abort; mutex.unlock(); QString value = "External API call"; emit valueChanged(value); } // Set _working to false, meaning the process can't be aborted anymore. mutex.lock(); _working = false; mutex.unlock(); qDebug()<<"Worker process finished in Thread "<<thread()->currentThreadId(); //Once 60 sec passed, the finished signal is sent emit finished(); }
worker.h
#ifndef WORKER_H #define WORKER_H #include <QObject> #include <QMutex> class Worker : public QObject { Q_OBJECT public: explicit Worker(QObject *parent = 0); /** * @brief Requests the process to start * * It is thread safe as it uses #mutex to protect access to #_working variable. */ void requestWork(); /** * @brief Requests the process to abort * * It is thread safe as it uses #mutex to protect access to #_abort variable. */ void abort(); private: /** * @brief Process is aborted when @em true */ bool _abort; /** * @brief @em true when Worker is doing work */ bool _working; /** * @brief Protects access to #_abort */ QMutex mutex; signals: /** * @brief This signal is emitted when the Worker request to Work * @sa requestWork() */ void workRequested(); /** * @brief This signal is emitted when counted value is changed (every sec) */ void valueChanged(const QString &value); /** * @brief This signal is emitted when process is finished (either by counting 60 sec or being aborted) */ void finished(); public slots: /** * @brief Does something * * Counts 60 sec in this example. * Counting is interrupted if #_aborted is set to true. */ void doWork(int initial); }; #endif // WORKER_H
The program compiles fine but while running, it gives
QObject::connect: No such signal QThread::requestUpdate(int)
The program is expected to execute the worker thread each time being invoked from mainWindow.cpp. But the program outputs:
Request worker start in Thread 0x7f0431575740 Request worker aborting in Thread 0x7f0431575740 Starting worker process in Thread 0x7f04252e5700 Worker process finished in Thread 0x7f04252e5700 Request worker start in Thread 0x7f0431575740 Request worker aborting in Thread 0x7f0431575740 Starting worker process in Thread 0x7f04252e5700 Worker process finished in Thread 0x7f04252e5700 Request worker start in Thread 0x7f0431575740 Request worker aborting in Thread 0x7f0431575740 Starting worker process in Thread 0x7f04252e5700 Worker process finished in Thread 0x7f04252e5700 Request worker start in Thread 0x7f0431575740 Request worker aborting in Thread 0x7f0431575740 Starting worker process in Thread 0x7f04252e5700 Worker process finished in Thread 0x7f04252e5700 Request worker start in Thread 0x7f0431575740 Request worker aborting in Thread 0x7f0431575740 Starting worker process in Thread 0x7f04252e5700 Worker process finished in Thread 0x7f04252e5700 Request worker start in Thread 0x7f0431575740 External API call External API call External API call External API call External API call Starting worker process in Thread 0x7f0424ae4700 Worker process finished in Thread 0x7f0424ae4700 External API call
Where the qDebug prints "External API call" 5 times after finishing thread executions, but is expected to print parallel. What might go wrong here?
-
I am working on a project for passing argument and return the values in between thread. So far I have tried:
mainwindow.cpp (slightly updated)
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // The thread and the worker are created in the constructor so it is always safe to delete them. thread = new QThread(); worker = new Worker(); worker->moveToThread(thread); connect(worker, SIGNAL(valueChanged(QString)), this, SLOT(addNewImage(QString))); connect(worker, SIGNAL(workRequested()), thread, SLOT(start())); // connect(thread, SIGNAL(started()), worker, SLOT(doWork(int))); connect(this, SIGNAL(requestUpdate(int)), worker, SLOT(doWork(int))); connect(worker, SIGNAL(finished()), thread, SLOT(quit()), Qt::DirectConnection); } MainWindow::~MainWindow() { worker->abort(); thread->wait(); qDebug()<<"Deleting thread and worker in Thread "<<this->QObject::thread()->currentThreadId(); delete thread; delete worker; delete ui; } void MainWindow::on_startButton_clicked() { int i=0; for(i=0;i<5;i++) // Run 5 times { // To avoid having two threads running simultaneously, the previous thread is aborted. worker->abort(); thread->wait(); // If the thread is not running, this will immediately return. int enc = 5; //worker->requestWork(); emit requestUpdate(enc); } } void MainWindow::addNewImage(QString enc) { qDebug(qUtf8Printable(enc)); }
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QThread> #include "worker.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; /** * @brief Thread object which will let us manipulate the running thread */ QThread *thread; /** * @brief Object which contains methods that should be runned in another thread */ Worker *worker; private slots: void on_startButton_clicked(); public slots: void addNewImage(QString enc); signals: void requestUpdate(int initial); }; #endif // MAINWINDOW_H
and worker.cpp
#include "worker.h" #include <QTimer> #include <QEventLoop> #include <QThread> #include <QDebug> Worker::Worker(QObject *parent) : QObject(parent) { _working =false; _abort = false; } void Worker::requestWork() { mutex.lock(); _working = true; _abort = false; qDebug()<<"Request worker start in Thread "<<thread()->currentThreadId(); mutex.unlock(); emit workRequested(); } void Worker::abort() { mutex.lock(); if (_working) { _abort = true; qDebug()<<"Request worker aborting in Thread "<<thread()->currentThreadId(); } mutex.unlock(); } void Worker::doWork(int initial) { qDebug()<<"Starting worker process in Thread "<<thread()->currentThreadId(); // Checks if the process should be aborted mutex.lock(); bool abort = _abort; mutex.unlock(); QString value = "External API call"; emit valueChanged(value); } // Set _working to false, meaning the process can't be aborted anymore. mutex.lock(); _working = false; mutex.unlock(); qDebug()<<"Worker process finished in Thread "<<thread()->currentThreadId(); //Once 60 sec passed, the finished signal is sent emit finished(); }
worker.h
#ifndef WORKER_H #define WORKER_H #include <QObject> #include <QMutex> class Worker : public QObject { Q_OBJECT public: explicit Worker(QObject *parent = 0); /** * @brief Requests the process to start * * It is thread safe as it uses #mutex to protect access to #_working variable. */ void requestWork(); /** * @brief Requests the process to abort * * It is thread safe as it uses #mutex to protect access to #_abort variable. */ void abort(); private: /** * @brief Process is aborted when @em true */ bool _abort; /** * @brief @em true when Worker is doing work */ bool _working; /** * @brief Protects access to #_abort */ QMutex mutex; signals: /** * @brief This signal is emitted when the Worker request to Work * @sa requestWork() */ void workRequested(); /** * @brief This signal is emitted when counted value is changed (every sec) */ void valueChanged(const QString &value); /** * @brief This signal is emitted when process is finished (either by counting 60 sec or being aborted) */ void finished(); public slots: /** * @brief Does something * * Counts 60 sec in this example. * Counting is interrupted if #_aborted is set to true. */ void doWork(int initial); }; #endif // WORKER_H
The program compiles fine but while running, it gives
QObject::connect: No such signal QThread::requestUpdate(int)
The program is expected to execute the worker thread each time being invoked from mainWindow.cpp. But the program outputs:
Request worker start in Thread 0x7f0431575740 Request worker aborting in Thread 0x7f0431575740 Starting worker process in Thread 0x7f04252e5700 Worker process finished in Thread 0x7f04252e5700 Request worker start in Thread 0x7f0431575740 Request worker aborting in Thread 0x7f0431575740 Starting worker process in Thread 0x7f04252e5700 Worker process finished in Thread 0x7f04252e5700 Request worker start in Thread 0x7f0431575740 Request worker aborting in Thread 0x7f0431575740 Starting worker process in Thread 0x7f04252e5700 Worker process finished in Thread 0x7f04252e5700 Request worker start in Thread 0x7f0431575740 Request worker aborting in Thread 0x7f0431575740 Starting worker process in Thread 0x7f04252e5700 Worker process finished in Thread 0x7f04252e5700 Request worker start in Thread 0x7f0431575740 Request worker aborting in Thread 0x7f0431575740 Starting worker process in Thread 0x7f04252e5700 Worker process finished in Thread 0x7f04252e5700 Request worker start in Thread 0x7f0431575740 External API call External API call External API call External API call External API call Starting worker process in Thread 0x7f0424ae4700 Worker process finished in Thread 0x7f0424ae4700 External API call
Where the qDebug prints "External API call" 5 times after finishing thread executions, but is expected to print parallel. What might go wrong here?
Hi
@sigmind said in QT thread not syncing:
or(i=0;i<5;i++) // Run 5 times
{
// To avoid having two threads running simultaneously, the previous thread is aborted.
worker->abort();
thread->wait(); // If the thread is not running, this will immediately return.
int enc = 5;
//worker->requestWork();
emit requestUpdate(enc);
}You are aborting your thread and then waiting on it to finish, therefore the output you get is correct. If you want to parallelise things, you'll have to start several threads in parallel.
-
@SGaist Thanks for pointing out. Modifying it like:
or(i=0;i<5;i++) // Run 5 times { // To avoid having two threads running simultaneously, the previous thread is aborted. //worker->abort(); //thread->wait(); // If the thread is not running, this will immediately return. int enc = 5; worker->requestWork(); emit requestUpdate(enc); }
returns result like this:
Request worker start in Thread 0x7f083eb3d740 Request worker start in Thread 0x7f083eb3d740 Request worker start in Thread 0x7f083eb3d740 Request worker start in Thread 0x7f083eb3d740 Request worker start in Thread 0x7f083eb3d740 Request worker start in Thread 0x7f083eb3d740 Starting worker process in Thread 0x7f082c93a700 Worker process finished in Thread 0x7f082c93a700 Starting worker process in Thread 0x7f082c93a700 Worker process finished in Thread 0x7f082c93a700 Starting worker process in Thread 0x7f082c93a700 Worker process finished in Thread 0x7f082c93a700 Starting worker process in Thread 0x7f082c93a700 Worker process finished in Thread 0x7f082c93a700 External API call Starting worker process in Thread 0x7f082c93a700 External API call External API call Worker process finished in Thread 0x7f082c93a700 Starting worker process in Thread 0x7f082c93a700 External API call Worker process finished in Thread 0x7f082c93a700 External API call External API call
Is it true that the "worker thread" is working parallely? Or should I do something more to run it parallel and synchronously? Thanks in advance.
-
Re-reading your code, your worker object looks a bit convoluted.
The most simple version is:
- Create a QThread object
- Create your worker object
- Move it to your QThread object
- Connect QThread's started signal to your worker object's
doWork
slot - Configure your worker with the parameters you want
- Call QThread's start method
In any case, can you explain exactly what you want to do ? Depending on that, maybe QtConcurrent might be a better choice.
-
What kind of API is that ?