Lehtim Lehtim - 3 months ago 27
C++ Question

Qt: Multithreading connect does not work

I want to connect two threads. One Thread is the Mainthread of my application the other on is a workerthread. I have based my code on the following example doc.qt.io/qt-5/. For me it does not work completely. I am sending a QString to my WorkerThread (this works) and want to send it afterwards back to the MainThread (does not work). Before asking why I am doing this that's just a very simple example. The real Code is much more complex but I have exactly the same problem. If those example would run I am very sure that the complex one would work too. Here the code:

Main.cpp

#include "Controller_C.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Controller_C Controller;
Controller.SendData("Hello World!");
return a.exec();
}


Controller_C.cpp

#include "Controller_C.h"
#include <qmessagebox.h>

Controller_C::Controller_C(QWidget *parent)
: QMainWindow(parent),
Worker(new Worker_C())
{
ui.setupUi(this);

Worker->moveToThread(&WorkerThread);
connect(&WorkerThread, SIGNAL(started()), this, SLOT(ThreadStarted()));
connect(this, SIGNAL(SendToWorker(QString)), Worker, SLOT(DoWork(QString)));
connect(Worker, SIGNAL(SendToController()), this, SLOT(ReceiveData()));
WorkerThread.start();
}

Controller_C::~Controller_C()
{

}

void Controller_C::SendData(QString aString)
{
QThread* Controller = QThread::currentThread();
QMessageBox::information(this, "Info", QString("We have send the following to the Worker Thread: %1").arg(aString));
emit SendToWorker(aString);
}

void Controller_C::ReceiveData(QString aString)
{
QThread* Controller = QThread::currentThread();
QMessageBox::information(this, "Info", QString("The Controller received the following: %1").arg(aString));
}


Controller_C.h

#ifndef CONTROLLER_C_H
#define CONTROLLER_C_H

#include <QtWidgets/QMainWindow>
#include "ui_Controller_C.h"
#include "Worker_C.h"
#include <qthread.h>

class Controller_C : public QMainWindow
{
Q_OBJECT

public:
Controller_C(QWidget *parent = 0);
~Controller_C();

void SendData(QString aString);

private:
Ui::Qt_TestEnvironmentClass ui;
Worker_C* Worker;
QThread WorkerThread;

signals:

void SendToWorker(QString);

public slots:

void ReceiveData(QString aString);
};

#endif // CONTROLLER_C_H


Worker_C.cpp

#include "Worker_C.h"
#include <qmessagebox.h>
#include <qthread.h>

Worker_C::Worker_C()
{

}

Worker_C::~Worker_C()
{

}

void Worker_C::DoWork(QString aString)
{
QThread* Worker = QThread::currentThread();
emit SendToController(aString);
}


Worker_C.h

#ifndef WORKER_C_H
#define WORKER_C_H

#include <QObject>

class Worker_C : public QObject
{
Q_OBJECT

public:
Worker_C();
~Worker_C();

public slots:

void DoWork(QString aString);

signals:

void SendToController(QString);

};

#endif // WORKER_C_H


Thanks for your help.

Answer

Like the way you definied the Slot/Signal in your header:

void ReceiveData(QString aString);
void SendToController(QString);

You should also use them like this in your connect:
connect(Worker, SIGNAL(SendToController(QString)), this, SLOT(ReceiveData(QString)));
Furthermore I would suggest you to use QApplication::processEvents() in your more complex code if you emit many signals. But that is just an idea when you have some more pending Events caused by your complex code.