How to start timers from the worker thread class in Qt? - multithreading

Declaration part of Controller class:
class ProtocolPacket: public QQuickItem
{
private:
Q_OBJECT
...
QThread objWorkerThread;
public:
ProtocolPacket();
~ProtocolPacket();
...
The constructor of controller class:
ProtocolPacket::ProtocolPacket()
{
ReadWriteSerialPort *objReadWriteSerialPort = new ReadWriteSerialPort;
objReadWriteSerialPort->moveToThread(&objWorkerThread);
connect(&objWorkerThread, &QThread::finished,
objReadWriteSerialPort, &QObject::deleteLater);
/// Following signals of ProtocolPacket class are connected to the corresponding
/// slots of thread class ReadWriteSerialPort.
connect(this, &ProtocolPacket::cameraValueChanged,
objReadWriteSerialPort, &ReadWriteSerialPort::receiveAndSendUpdatedCameraValue);
...
...
objWorkerThread.start();
}
The constructor of worker thread class:
ReadWriteSerialPort::ReadWriteSerialPort()
{
...
serialPort.setPortName ("/dev/ttyUSB0");
serialPort.setBaudRate (QSerialPort::Baud19200);
if(serialPort.open (QIODevice::ReadWrite))
{
serialPort.setDataBits(QSerialPort::Data8);
serialPort.setParity(QSerialPort::NoParity);
serialPort.setStopBits(QSerialPort::OneStop);
}
objWriter = new SerialPortWriter(&serialPort);
objReader = new SerialPortReader(&serialPort);
timerSendVelocityPackets = new QTimer(this);
connect (timerSendVelocityPackets, SIGNAL (timeout()),
this, SLOT (sendVelocityPacket()));
timerSendHealthFeedbackPackets = new QTimer(this);
connect (timerSendHealthFeedbackPackets, SIGNAL (timeout()),
this, SLOT (formAndSendHealthFeedbackPackets()));
timerReceivePackets = new QTimer (this);
connect (timerReceivePackets, SIGNAL (timeout()),
this, SLOT (receiveAndUnpackPacket()));
timerReceivePackets->start (300);
}
I am receiving the error:
QObject::startTimer: Timers cannot be started from another thread
What am I doing wrong?
I wish to start the timers from the worker class: ReadWriteSerialPort

Every object constructed in the object that you move to another thread must have its parent set:
class ReadWriteSerialPort : public QObject {
QSerialPort serialPort { this }; // important
QTimer timerSendVelocityPackets { this }; // etc.
...
};
You also must ensure that there are no direct calls into the thread-unsafe methods of ReadWriteSerialPort from other threads.
Furthermore, unless you're polling for data, the timer-driven packet receive is incorrect. You should act on the readyRead signal issued by the serial port.
I also question the separate reader and writer: Usually these tasks both need to be aware of the expected state of the target device, so separating them might be unhelpful. It's hard to say without seeing more of the code.

Related

delete Q_GLOBAL_STATIC in correct thread

I have an application consisting of an executable and several DLLs.
The exe links a dll statically. This dll creates a worker thread which instantiates a Q_GLOBAL_STATIC object (first access). So this object (derived from QObject) lives in this worker thread.
At program exit this object needs to be destroyed in the worker thread. But it is actually destroyed when the static dll gets unloaded, which is happening in the main thread.
How do I delete this global static object in the correct thread?
I tried manually deleting it when my worker thread finishes. But this results in a crash after my destructor returns.
You need to explicit call destructor on that object like this obj.~Test(); then after check if object is destroyed obj.isDestroyed() if it is not working.
Use QLibrary to load and unload dll ( https://doc.qt.io/archives/qt-4.8/qlibrary.html). Where in Q_GLOBAL_STATIC documentation(https://doc.qt.io/qt-5/qglobalstatic.html#destruction) it is mention that destructor will be called on unload of library or atexit() funciton of application.
I'd like to share my solution. To make it work, I introduced a simple private class which I use as a QGlobalStatic. This global object of this class holds the real singleton object and allows safe deletion of it in the correct thread.
The header file:
class MySingletonPrivate;
class MySingleton : public QObject
{
Q_OBJECT
public:
static MySingleton* instance();
static void deleteInstance();
protected:
MySingleton( QObject *parent = nullptr );
~MySingleton();
friend class MySingletonPrivate;
};
The cpp file:
class MySingletonPrivate
{
public:
MySingletonPrivate()
: inst( new MySingleton() )
{
QObject::connect( QThread::currentThread(), &QThread::finished, inst, &MySingleton::deleteLater );
}
~MySingletonPrivate()
{
Q_ASSERT( inst.isNull() );
}
MySingleton* instance() const
{
return inst;
}
private:
QPointer< MySingleton > inst;
};
Q_GLOBAL_STATIC( MySingletonPrivate, s_instance );
MySingleton* MySingleton::instance()
{
return s_instance->instance();
}
void MySingleton::deleteInstance()
{
delete s_instance->instance();
}
Using the signal QThread::finished the global instance is deleted at the end of the worker thread.
I left out the include instructions and the constructor and destructor implemention to make the answer shorter.
Of course, the first call to MySingleton::instance() must happen in the worker thread.

Permanent Threads in QT

I'm new in QT...and i haven't time. I have a GUI with 3 labels that must be update from 3 different threads (permanents, that invoke 3 different methods) every 10 secs. What is the best way to make this? thanks in advance!
You should use Qt signaling mechanism.
class QWindow : QMainWindow
{
//this macro is important for QMake to let the meta programming mechanism know
//this class uses Qt signalling
Q_OBJECT
slots:
void updateLabel(QString withWhat)
...
};
And now You just need to connect this slot to some signal
class SomeThreadClass : QObject
{
Q_OBJECT
...
signals:
void labelUpdateRequest(QString withwhat);
};
in the constructor of the window
QWindow::QWindow(QWidget* parent) : QMainWindow(parent)
{
m_someThread = new SomeThreadClass();
//in old style Qt, now there's a mechanism for compile time check
//don't use pointers, you need to free them at some point and there might be many receivers
//that might use it
connect(m_someThread, SIGNAL(labelUpdateRequest(QString)), this, SLOT(updateLabel(QString));
...
}
now just at some point in the thread:
SomeThreadClass::someMethod()
{
//do something...
emit labelUpdateRequest(QString("Welcome to cartmanland!"));
//this will be received by all classes that call connect to this class.
}
Hope that helps :)

How to properly stop thread in class when the class is exposed to QML

I have a class that is exposed to QML:
qmlRegisterType("SerialThread", 1, 0, "SerialThread");
This class inherits QThread and the QThread.start() is called from QML.
When the user closes the application, how do I properly exit the thread before the program terminates?
In the destructor, you should call quit() followed by wait(). Since, hopefully, you've made QML own the thread object, it will destruct it - feel free to verify that the destructor is, in fact, executed.
If you don't spin an event loop in the thread, then you must reimplement quit() to set your own stop flag. Since you hide the underlying non-virtual quit(), your "thread" is not really a QThread anymore, and you must inherit from QThread privately - it's a semantic error to do otherwise (and leads to bad bugs).
How such bugs happen? Since you can pass your "not quite" a thread somewhere a QThread is expected, those users of it are free to assume it's a real thread, not a "not quite one", and call QThread::quit() method, which is a no-op without an event loop. Thus bugs.
To maintain LSP, if you need to override non-virtual public methods, you must privately inherit from the parent class, since it's not usable in places where its parent would be usable.
class MyThread : private QThread {
Q_OBJECT
Q_DISABLE_COPY(MyThread)
volatile bool m_stop;
void run() { ... }
public:
MyThread(QObject * parent = nullptr) : QThread(parent) { ... }
void quit() { m_stop = true; }
// It's important to fully qualify the Priority type, otherwise moc will generate
// wrong code.
Q_SLOT void start(QThread::Priority priority = InheritPriority) {
if (isRunning()) return;
m_stop = false;
QThread::start();
}
using QThread::isRunning;
using QThread::isFinished;
bool isInterruptionRequested() const { return m_stop; }
~MyThread() {
quit();
wait();
}
// Publicly we're only a QObject, not a thread
operator QObject&() { return *this; }
operator const QObject&() const { return *this; }
void run() {
while (!m_stop) { ... }
}
};
You can call thread.stop() and check thread.isRunning() before returning exit value in the main.

Qt (4.8) simplest way to call slot with AutoConnection behavior

I have something like this:
class Thing : public QObject {
...
public slots:
void doSomething ();
...
};
I then have an object that manages Things, like this:
class ManyThings : public QObject {
...
public:
void makeThingDoSomething (int thingIndex);
private:
QVector<Thing *> things_;
...
};
My question is this: The Things in ManyThing's collection are scattered among a few different threads. I'd like makeThingDoSomething(int) to call the things_[thingIndex]->doSomething() slot as if the slot was called from a signal connected with Qt::AutoConnection. Essentially this, but using Qt's queuing mechanism if the Thing is on a different thread than the caller:
void ManyThings::makeThingDoSomething (int thingIndex) {
// i want to do this AutoConnection style, not direct:
things_[thingIndex]->doSomething();
// doesn't *need* to block for completion
}
What's the simplest way to set this up? I could make a signal in ManyThings and connect it to each of the Thing's slots, but then emitting that signal would call the slot on every Thing, not just a specific one. Is there some way to easily set up connections so that I can connect the same signal to different object's slots depending on an index parameter passed to the signal, or something? Or some way to call the slot using Qt's signal/slot mechanism without actually having to create a signal?
Try using QMetaObject::invokeMethod:
void ManyThings::makeThingDoSomething(int thingIndex) {
QMetaObject::invokeMethod(things_[thingIndex], "doSomething",
Qt::AutoConnection);
}
Note that doSomething will likely have to remain a slot if you use this approach.

QT: run independent thread from other thread

Let me just give you an example.
class B : public QThread {
public:
void run() {
}
};
class A : public QThread {
public:
void run() {
b1.start(); b2.start();
}
protected:
B b1, b2;
};
I want A::b1 and A::b2 to run as completely independent threads, not sharing resources of parent thread (A). Is there any way to specify main thread as parent thread of b1 and b2?
I've also looked at QThreadPool and QRunnable, and i don't understand, how is it possible to manage all runnables (for example, stop one of them, and then run it again) of threadpool.
Subclassing QThread is the wrong way of creating threads in Qt. QObject provides the function moveToThread which simply allows you to change the thread affinity of an object and its children.
Changes the thread affinity for this object and its children. The
object cannot be moved if it has a parent. Event processing will
continue in the targetThread.
To move an object to the main thread, use QApplication::instance() to
retrieve a pointer to the current application, and then use
QApplication::thread() to retrieve the thread in which the application
lives.
So what you should do is to is to inherit from QObject instead of QThread and change your run function to move the B objects to other threads.
Sample Code (untested)
class B : public QObject {
Q_OBJECT
public:
void run() {
}
};
class A : public QObject {
Q_OBJECT
public:
void run() {
b1Thread = new QThread;
b2Thread = new QThread;
b1.moveToThread(b1Thread);
b2.moveToThread(b2Thread);
b1.run();
b2.run();
}
protected:
B b1, b2;
private:
QThread* b1Thread, b2Thread; // Delete them in the destructor.
};
You could construct the threads in main.cpp and pass them to the B class as arguments.
Notice the following concerning moveToThread
this function can only "push" an object from the current thread to
another thread, it cannot "pull" an object from any arbitrary thread
to the current thread.

Resources