Sending parameters from GUI thread to work thread - c++

I have got some problem in Qt.
I assign some parameters in GUI thread:
newton.h (work thread) :
class Newton : public QThread
resic.cpp (GUI thread) :
.
.
.
Newton mythread;
resic::resic(QWidget *parent) :
QWidget(parent),
ui(new Ui::resic)
{
ui->setupUi(this);
mythread.start();
}
void resic::on_PushButton_clicked()
{
w1=ui->doubleSpinBox_2->value();
um1=ui->doubleSpinBox->value();
alpha1=ui->doubleSpinBox_3->value();
et01=ui->doubleSpinBox_4->value();
Er1=ui->doubleSpinBox_11->value();
Rx1=ui->doubleSpinBox_12->value();
xa1=ui->doubleSpinBox_8->value();
xb1=ui->doubleSpinBox_9->value();
q1=ui->doubleSpinBox_10->value();
ya1=(q1-2*q1);
yb1=ui->doubleSpinBox_10->value();
maxl1=ui->spinBox->value();
}
And I want to send these parameters after click on the button to the work thread and then run some calculation in this work thread.
But I don't know how send parameters.
Can you give me some advice, please?
Thank you very much.

A simple solution to running a piece of code in a worker thread is to leverage Qt Concurrent framework. Another solution is to put the worker into a QObject, and use a QThread directly.
struct Parameters {
double w1, um1, alpha1, et01, ...;
};
struct Result {
...
};
Result calculate(const Parameters & p) {
...
}
class resic : public QWidget {
...
QFutureWatcher<Result> m_futureWatcher;
QScopedPointer<Ui::resic> ui;
Q_SLOT void onResults();
...
};
resic::resic(QWidget * parent) : QWidget(parent), ui(new Ui::resic)
{
connect(&m_futureWatcher, SIGNAL(finished()), SLOT(onResults()));
}
resic::~resic() {}
Parameters resic::get()
{
Parameters p;
p.w1=ui->doubleSpinBox_2->value();
p.um1=ui->doubleSpinBox->value();
p.alpha1=ui->doubleSpinBox_3->value();
p.et01=ui->doubleSpinBox_4->value();
...
return p;
}
void resic::on_PushButton_clicked()
{
Parameters const p(get());
QFuture<Result> future = QtConcurrent::run(&calculate);
m_futureWatcher.setFuture(future);
}
void resic::onResults()
{
Result const r = m_futureWatcher.result();
...
}

It is important to remember that a QThread object usually lives in the thread where it was created, not in the thread that it manages. This oft-overlooked detail means that a QThread's slots will be executed in the context of its home thread, not in the context of the thread it is managing. For this reason, implementing new slots in a QThread subclass is error-prone and discouraged.
You can inherit the class "Newton" from QObject create your object of this class on the heap and move it to a new thread.
It can be done like:
mythread = new Newton();
QThread * th = new QThread();
mythread->moveToThread(th);
QObject::connect(th,SIGNAL(started()),mythread,SLOT(OnStarted()));
QObject::connect(th,SIGNAL(finished()),mythread,SLOT(OnFinished()));
th->start();
Your initialization and termination tasks in the class Newton should be done in OnStarted() and OnFinished() slots respectively.
Now you can implement a slot in your worker thread which runs the calculations. You can connect a signal in your GUI thread to that slot which contains the arguments you want to send. When emitting that signal along the arguments, the calculation slot in the working thread is started with the appropriate arguments.

Related

QT slot not getting called on main thread

From the thread context of a slot in my QT GUI application (upon button push), I am trying to launch a worker thread to update other another part of the GUI with the results of a CPU intensive calculation - these results will update a table or a google like map widget - so this needs to occur in the main QT application thread where it is safe to update these widgets.
The problem I have is that the updateGUIWidget slot never gets called unless I change the connection type to Qt::DirectConnection - in which case it gets called in the worker thread (where it is unsafe to update the GUI). I checked the results of each of the connect calls and they are fine, it seems that there is some issue with the event loop somewhere. I'm not sure if I need to allocate the thread and the worker objects as members of the mainwindow or if its OK to do so from stack variables in the slot.
void
mainwindow::on_importSimulatedFlight_clicked()
{
// experimental worker thread model adapted from YouTube tutorial
// by Giuseppe di Angelo https://www.youtube.com/watch?v=BgqT6SIeRn4
// auto thread = new QThread;
// note worker created in gui thread here - we will move its thread
// affinity to 'thread' below before starting it.
auto thread = new QThread;
auto worker = new Worker;
connect(thread, &QThread::started, worker, &Worker::doWork);
// connect(worker, &Worker::progressUpdate, this, &mainwindow::updateGUIWidget, Qt::DirectConnection);
connect(worker, &Worker::progressUpdate, this, &mainwindow::updateGUIWidget, Qt::QueuedConnection);
connect(worker, &Worker::workDone, thread, &QThread::quit);
connect(thread, &QThread::finished, worker, &Worker::deleteLater);
// move worker to separate thread
worker->moveToThread(thread);
thread->start();
}
The mainwindow has a slots declared in mainwindow.h as follows:
class mainwindow : public QMainWindow
{
Q_OBJECT
public:
explicit mainwindow(QWidget *parent = Q_NULLPTR);
~mainwindow();
...
public slots:
void on_importSimulatedFlight_clicked();
void updateGUIWidget(const param& rParam);
...
}
and implemented in mainwindow.cpp as follows:
void
mainwindow::updateGUIWidget(const param& rParam)
{
... update widget components with rParam partial result here
}
and my worker is as follows:
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork() {
const QString result;
for (int i=0; i<5; i++) {
const MMRTimedRecord foo;
// QThread::sleep(1);
emit progressUpdate(foo);
}
emit workDone(result);
}
signals:
void progressUpdate(const MMRTimedRecord&);
void workDone(const QString &result);
};
The reason it isn't working is because there's a serious flaw in your code: you are trying to emit a reference to a local variable to be handled in an slot on a different thread. That is a recipe for disaster.
When you are using Qt::QueuedConnection, you MUST emit by value, like this:
void progressUpdate(MMRTimedRecord val);
That means that your MMRTimedRecord must be copyable, and correspondingly, your slot must also accept by value. And why is there a mismatch between the signal progressUpdate(const MMRTimedRecord&) and the slot updateGUIWidget(const param& rParam); ?
You can check this answer for a possible solution. You can do
MainThreadEvent::post([&]()
{
// gui update stuff
}
);
in your slot to do the gui update in the main thread, but it is a crude approach to be sure. Despite this, I do something like this all the time. Be careful of dangling pointers and references (use QPointer)..., as the issued event is independent of the issuing object. Alternatively, use the timer approach.
It’s really easy – and you shouldn’t be managing any threads manually:
void Ui::slot() {
QtConcurrent::run([this]{
auto result = compute();
QMetaObject::invokeMethod(this, [this, r = std::move(result)]{
m_widget.setSomething(r);
});
});
}
The type of the data you compute should be movable.

qt emitting a signal across threads by moving the object to

I'm looking for correct pattern to use it in Qt-based app for async processing.
this is a simplified class which should receive a signals
class Receiver : public QObject {
Q_OBJECT
public:
explicit Receiver(QObject *parent = nullptr) : QObject(parent) { }
public slots:
void onNewMessage(Message message) {
// ...
}
};
the creating of the instance of this class is a dynamic (also simplifed, really - an array of the objects for message processing).
Receiver* r;
// ...
if (r == nullptr) {
r = new Receiver{};
r->moveToThread(new QThread);
connect(this, &MessageGenerator::messageCompleted, r, &Receiver::onNewMessage);
}
in main function also exists a registration:
qRegisterMetaType<Message> ("Message");
the question is why slot is never called?
in case of the removing Thread stuff (moveTOThread) then all works fine ,
but I'd prefer to have a processing in event loops in different threads
According to the doc:
Constructs a new QThread to manage a new thread. The parent takes ownership of the QThread. The thread does not begin executing until start() is called.
Do you call method start, like this?
r = new Receiver{};
t = new QThread();
r->moveToThread(t);
connect(this, &MessageGenerator::messageCompleted, r, &Receiver::onNewMessage);
t->start();

Correct way to signal QObject on another thread?

Let's say I have a slave object that lives in another thread. I want to tell it to do A, B, C on that thread. I can think of 3 ways of doing it:
(1) Using QTimer::singleShot
(2) Using QMetaObject::invokeMethod
(3) Creating another master object and connecting its signal to the slave
Following is an example:
class slave : public QObject
{
QThread thread_;
friend class master;
void do_A(params);
void do_B(params);
void do_C(params);
public:
slave() { thread_.start(); moveToThread(&thread_); }
~slave() { thread_.quit(); thread_.wait(); }
void que_A(params) { QTimer::singleShot(0, [&](){ do_A(params); }); } // (1)
void que_B(params) { QMetaObject::invokeMethod(this, "do_B", params); } // (2)
}
class master : public QObject // (3)
{
Q_OBJECT
public:
master(slave* s) { connect(this, &master::que_C, s, &slave::do_C); }
void do_C(params) { emit que_C(params); }
signals:
void que_C(params);
}
My concerns are:
(1) I am abusing QTimer.
(2) Using strings for signals/slot is so qt4. Qt5 uses new syntax.
(3) Too much boilerplate.
Is any of the methods considered more correct compared to the others? Or can anybody think of a better way?
Please include your reasoning (not just opinion) why one method should be chosen over others.
UPDATE:
In my real-world application I have another class -- let's call it owner -- that owns several slaves. The owner needs to tell different slaves to do different things (A, B or C) depending on user input. The slaves are stateful objects, so I cannot see an easy way of using concurrency functions (eg, std::async or QtConcurrency).
Well, I will not comment (1) and (2) but I must say that (3) is the one usually used. However, I understand your concern about too much boilerplate. After all, creating a separate signal, say doActionA(), connecting it via QueuedConnection to some real actionA() and at last emitting it... too much noise and useless moves.
Indeed, the only benefit it gives you is a loose coupling (you can send a signal being not aware of existence of slots connected to it). But if I create a signal with a name doActionA() of course I am aware of actionA() existence. So then the question is starting to raise "Why do I have to write all this stuff?"
Meanwhile, Qt kind of provides the solution to this problem giving you the ability to post your own events to any event loop (and as you know QThread has one). So, implement it once and you do not need to write a lot of connect emit stuff any more. Also, I suppose I is more efficient because all in all, every slot invokation via QueuedConnection just posts an event in an event loop.
Here InvokeAsync posts the event for member function execution into the event loop of the thread where QObject lives:
#include <QCoreApplication>
#include <QEvent>
#include <QThread>
#include <string>
#include <iostream>
#include <type_traits>
#include <functional>
template<typename T, typename R, typename ... Params, typename... Args>
void InvokeAsync(T* object, R (T::*function)(Params...), Args&&... args)
{
struct Event : public QEvent
{
std::function<R ()> function;
Event(T* object, R (T::*function)(Params...), Args&& ... args)
: QEvent{ QEvent::None },
function{ std::bind(function, object, std::forward<Args>(args)...) }
{
}
~Event() { function(); }
};
QCoreApplication::postEvent(object, new Event{ object, function, std::forward<Args>(args)... });
}
struct Worker : QObject
{
void print(const std::string& message, int milliseconds)
{
QThread::currentThread()->msleep(milliseconds);
std::cout << message
<< " from thread "
<< QThread::currentThreadId() << std::endl;
}
};
int main(int argc, char* argv[])
{
QCoreApplication a(argc, argv);
std::cout << "GUI thread " << QThread::currentThreadId() << std::endl;
QThread thread;
thread.start();
Worker worker;
worker.moveToThread(&thread);
InvokeAsync(&worker, &Worker::print, "Job 1", 800);
InvokeAsync(&worker, &Worker::print, "Job 2", 400);
InvokeAsync(&worker, &Worker::print, "Job 3", 200);
a.exec();
return 0;
}
Output:
GUI thread 00000000000019C8
Job 1 from thread 00000000000032B8
Job 2 from thread 00000000000032B8
Job 3 from thread 00000000000032B8
As you see all jobs where done in a different thread in order of their invocation. Qt guarantees that events with the same priority are processed in order as they were posted.
Also it is OK, if worker lives in GUI thread. Events will be just posted in GUI event loop and processed later (that is why I called those Async).
If you see any mistakes or have some remarks, please, write in comments and we will figure it out.
I am not pretty sure I understood well the question.
So I will explain here how to manage thread in Qt (in summarized way).
First, QThreadclass is not really meant to be inherited from.
Instead, make something like this :
class Slave : public QObject {
Slave(QThread *thread) {moveToThread(thread);)
};
QThread thread;
Slave slave(&thread);
After, you normally can use signal and slots in the normal way.
However, if your objective is only to "run a function inside another thread", maybe QConcurrent could be a better way?
In fact, the Qt documentation provides a very nice example that probably answers your question on how to use QThread. It's the following:
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString &parameter) {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
The idea here is simple. You have a worker, which is running in the thread. You also have the controller, which is basically your main thread that submits work to the other thread. The thread will (thread-safely) emit the resultReady() signal when it's finished. Signals and slots are thread-safe here, as long as they use Qt::QueuedConnection to communicate.

Type conversion and QThreadStorage warning while using QThread?

I'm very new to using QThread. I'm using QThread to grab images from an Axis Ip Camera. In the following snippet of the code I'm moving the camera class to a new thread:
QThread camThread;
camera = new AxisNetworkCamera();
camera->moveToThread(&camThread);
camThread.start();
connect(camera, SIGNAL(imageUpdate(QImage)), this, SLOT(upDateImage(QImage)));
connect(camera, SIGNAL(cameraDisconnected()), this, SLOT(cameraDisconnected()));
connect(&camThread, &QThread::finished, &camThread, &QThread::deleteLater);
connect(camera, &AxisNetworkCamera::destroyed, &camThread, &QThread::quit);
I'm invoking the function that starts the camera:
QMetaObject::invokeMethod(camera, "deviceStartup", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(streamUrl)));
The application runs fine and also closes fine when I close it, but what I'm worried is about a couple of warning messages.
First one is when I start the camera:
Type conversion already registered from type QPair<QByteArray,QByteArray> to type QtMetaTypePrivate::QPairVariantInterfaceImpl
2nd one is when I close the application:
QThreadStorage: Thread 0x7fffb8004da0 exited after QThreadStorage 7 destroyed
Should I be worried about these messages? Do they, specially the second 1, mean any memory mismanagement?
Thanks
The code you've posted makes no sense. QThread is not dynamically allocated so you cannot delete it: the deleteLater call will crash. Probably it never gets executed, since you show no code that would stop the thread anyway. There's also no point in destroying the thread after the camera has been destroyed.
The simplest way to do things safely would be to hold the camera and thread by value in your class, and declare them in proper order so that the thread is destroyed before the camera. At that point, the camera becomes threadless and will be safe to destroy in any thread.
There's also a nicer way to invoke methods in remote threads than using invokeMethod:
class Thread : public QThread {
using QThread::run; // final
public:
Thread(QObject*parent = 0): QThread(parent) {}
~Thread() { quit(); wait(); }
};
// See http://stackoverflow.com/a/21653558/1329652 for details about invoke.
template <typename F> void invoke(QObject * obj, F && fun) {
if (obj->thread == QThread::currentThread())
return fun();
QObject src;
QObject::connect(&src, &QObject::destroyed, obj, std::forward<F>(fun));
}
class MyObject : public QObject {
Q_OBJECT
AxisNetworkCamera camera;
Thread camThread { this };
Q_SLOT void updateImage(const QImage &);
Q_SLOT void cameraDisconnected();
public:
MyObject(QObject * parent = 0) : QObject(parent)
{
connect(&camera, &AxisNetworkCamera::imageUpdate, this, &MyObject::updateImage);
connect(&camera, &AxisNetworkCamera::cameraDisconnected, this, &MyObject::cameraDisconnected);
camera.moveToThread(&camThread);
camThread.start();
}
void startCamera(const QString & streamUrl) {
invoke(&camera, [=]{ camera.deviceStartup(streamUrl); });
}
};

Create Thread in QDialog and emit signals to QDialog in Qt

I created an application that has a mainwindow and from this window creates a QDialog. This QDialog should create a RenderThread that emits received images from the camera or in the example emits text. When i debug this it seems that the connection is never made as adding a breakpoint in the slot CameraWindow::debugSomething does not get caught. Whats wrong ?
I followed this example: http://qt-project.org/doc/qt-4.8/threads-mandelbrot.html but it seems that i've done something wrong.
qtDEVC::qtDEVC(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
connect (ui.pushButton_startCam, SIGNAL( clicked() ),this,SLOT( startCam() ) );
/**Threading*/
CameraWindow camWindow = new CameraWindow(this);
}
int qtDEVC::startCam()
{
camWindow.show();
camWindow.startCaptureThread();
}
CameraWindow Class:
CameraWindow::CameraWindow(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
connect(&thread, SIGNAL(sendText(std::string)),
this, SLOT(debugSomething(std::string)));
}
void CameraWindow::debugSomething(std::string something){
QString somethings(something.c_str());
qDebug()<<somethings;
}
int CameraWindow::startCaptureThread(){
RenderThread *thread = new RenderThread(this, guid, CLEYE_COLOR_RAW, CLEYE_VGA, 50);
thread->StartCapture(); //starts thread in low priority and sets _running to true
}
CameraWindow header
class CameraWindow : public QDialog
{
Q_OBJECT
public:
CameraWindow(QWidget *parent = 0);
~CameraWindow();
Ui::CameraWindow ui;
public slots:
int startCaptureThread();
void debugSomething(QString);
private:
RenderThread thread;
};
RenderThread Class
void RenderThread::run()
{
// image capturing loop
while(_running)
{
qDebug()<<("render while()"); //is printed with qdebug correctly
if (restart)
break;
if (abort)
return;
qDebug("it"); //is also printed with qdebug correctly
emit sendText(text);
}
RenderThread header
class RenderThread : public QThread
{
Q_OBJECT
public:
RenderThread(QObject *parent, GUID cameraGUID, CLEyeCameraColorMode mode, CLEyeCameraResolution resolution, float fps);
RenderThread();
~RenderThread();
bool StartCapture();
signals:
void sendText(QString &text);
protected:
void run();
private:
QMutex mutex;
QWaitCondition condition;
//some more private variables for construction
};
I think that this creation seems somehow wrong: RenderThread *thread = new RenderThread(this);
The first thing that's worrying about the question is the word "RenderThread". Note that Qt only allows rendering on the main thread. You can create separate threads for calculations of image data, but whenever you use a painter and draw objects, that must happen on the main thread. However, If you're just going to capture the image and pass that to the main thread, via signals and slots, then that should be ok.
Secondly, whilst you've not shown all your code, I'm assuming from the function called RenderThread::run() and from the Qt example that you may have inherited from QThread here. If this is the case, please note that this is not how to use QThread. Instead, you should have your class inherit from QObject and move that to a QThread. You can read about how to use QThread properly here.
I know it's a Qt example that you've followed, but even the guys at Qt think it's a bad idea. Here's an article of how to really use QThreads.
With that in mind, here's an outline of how I would use QThread for this: -
class CameraWindow : public QDialog
{
private:
CameraObject* m_pCamObject;
};
class CameraObject : public QObject
{
Q_OBJECT
public:
private slots:
startCaptureThread();
private:
};
int CameraWindow::startCaptureThread()
{
m_pCamObject = new CameraObject;
QThread* pThread = new QThread;
this->moveToThread(pThread); // CameraObject will run on the new thread
connect(pThread, SIGNAL(started()), m_pCamObject, SLOT(startCaptureThread()));
connect(pThread, SIGNAL(finished()), pThread, SLOT(deleteLater()); // clear up when
finished
pThread->start();
}
Note that here is a CameraObject, separated from the CameraWindow. The QThread is just a controller of the thread and keeps a clean separation from the CameraObject.
Another reason for handling threads this way is that you can move multiple QObject instances to the new thread, rather than always creating a new thread per object. If you've more threads than CPU cores, you're unlikely to gain by creating yet another thread.
In the constructor of CameraWindow class, you are connecting a RenderThread's signal but it is not the same object which is started in startCaptureThread. Change your startCaptureThread like this:
int CameraWindow::startCaptureThread()
{
thread.StartCapture(); //starts thread in low priority and sets _running to true
}
In this method, the thread member of CameraWindow is started.
P.S.: post the headers too, we can't see the members from this code.
In the mentioned example, CameraWindow class holds a RenderThread thread variable, not a RenderThread *thread.
You are connecting a pointer address in your connect call:
connect(&thread, SIGNAL(sendText(std::string)),
this, SLOT(debugSomething(std::string)));
Try to use a good address:
connect(thread, SIGNAL(sendText(std::string)),
this, SLOT(debugSomething(std::string)));
This is not a tested answer.