Howto make a simple Qt console application with multithreading? - c++

I have a very difficult time of understanding how to make a simplest possible working
multithreaded Qt console application.
I have read tons of stuff on how to use QThread class.
Some of them say subclass QThread, others say use worker class wrapper for QThread.
After several tries and retries I could still not make a working multithreaded
Qt console application.
Right now I don't need any fancy Qt Gui.
Can someone please help me to fill the threading parts of the example code ?
It just reads one line at the time from text file and the idea is that each thread (I want to use 4 threads) that is not busy at the moment will print that line to stdout with std::cout as soon as possible. Just print it, no other fancy processing stuff for now to keep this simple for me.
#include <QCoreApplication>
#include <QFile>
#include <iostream>
/* QThread stuff here */
/* Don't know how to make it */
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
/* Create four instances of threads here and
put them to wait readed lines */
QFile file("file.txt");
file.open(QIODevice::ReadOnly | QIODevice::Text);
while(!file.atEnd()) {
/* Read lines here but where should they be saved?
Into a global variable like QList<QByteArray> list ?
So that each thread can read them from there or where ???? */
??? = file.readLine();
}
file.close();
a.exit();
}

Putting the Functionality in a Slot in a QObject
The key points are:
Remember that each QObject has a certain thread() that it "lives" in. Each thread can have an event loop running there. This event loop will deliver the events sent to the objects that "live" in this thread.
Do not derive from QThread. Start stock QThreads. They'll start an even event loop in the default implementation of QThread::run().
Implement your functionality in a slot (or a Q_INVOKABLE) method. The class obviously has to derive from QObject.
The magic happens when you send signals (using signal-slot connection, not directly) to the slot in #3. The connection from the notifier, running in the GUI thread, to the notified objects is done automatically using the Qt::QueuedConnection since the sender and the receiver objects live in different threads.
Sending a signal to such an object results in posting an event to the event queue of the thread the object is in. The event loop's event dispatcher will pick those events and call the appropriate slots. This is the power of Qt - a lot of useful stuff can be done for you.
Note that there is no notion of a "currently busy" thread. The threads execute short slots of the objects that live there. If you want to move threads between a "busy" and "not busy" states, then you'd need extra code for that.
Another way of implementing it would be to derive from QRunnable and use QThreadPool. That's in another answer.
main.cpp
#include <QCoreApplication>
#include <QTextStream>
#include <QThread>
#include <QFile>
#include <cstdio>
class Notified : public QObject {
Q_OBJECT
QTextStream m_out;
public:
Q_SLOT void notify(const QString & text) {
m_out << "(" << this << ") " << text << endl;
}
Notified(QObject *parent = 0) : QObject(parent), m_out(stdout) {}
};
class Notifier : public QObject {
Q_OBJECT
Q_SIGNAL void notification(const QString &);
public:
Notifier(QObject *parent = 0) : QObject(parent) {}
void notifyLines(const QString & filePath) {
QFile file(filePath);
file.open(QIODevice::ReadOnly | QIODevice::Text);
while (! file.atEnd()) {
emit notification(file.readLine());
}
file.close();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QObjectList notifieds;
QList<QThread*> threads;
Notifier notifier;
for (int i = 0; i < 4; ++i) {
QThread * thread = new QThread(&a); // thread owned by the application object
Notified * notified = new Notified; // can't have an owner before it's moved to another thread
notified->moveToThread(thread);
thread->start();
notifieds << notified;
threads << thread;
notified->connect(&notifier, SIGNAL(notification(QString)), SLOT(notify(QString)));
}
notifier.notifyLines("file.txt");
foreach (QThread *thread, threads) {
thread->quit();
thread->wait();
}
foreach (QObject *notified, notifieds) delete notified;
a.exit();
}
#include "main.moc"

For your purposes I would not use QThread at all but the classes from QtConcurrent.
Something simple like (assuming you have C++11):
while(!file.atEnd()) {
QString line = file.readLine();
QtConcurrent::run([line]
{
qDebug() << line;
});
}
Though I'm still not sure what this should give you on a high level.

Below link can be useful for you for the information related to using threads in Qt
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
If you only want file reading to be done in Asynchronous ways Qt is having several alternate techniques like QtConcurrent.
http://qt-project.org/doc/qt-4.8/threads-qtconcurrent.html
Here is some example code to help you for using QtConcurrent
Running a Function in a Separate Thread
extern QString aFunction();
QFuture<void> future = QtConcurrent::run(aFunction);
aFunction should contain the code for reading the file .
You can return the read data in the following way
QFuture<QString> future = QtConcurrent::run(aFunction);
...
QString result = future.result();
Note that the QFuture::result() function blocks and waits for the result to become available. Use QFutureWatcher to get notification when the function has finished execution and the result is available.
Hope this helps. All the above code is taken from Qt documentation.

Putting the functionality in a QRunnable
Perhaps the solution that's closest to your explicit needs would use a QThreadPool. It does what you want: it picks a non-busy thread from its pool, and runs the worker there. If there are no free threads, it'll add the runnable to a run queue that gets drained each time a free thread becomes available.
Note, though, that your explicit wish of having a thread state, namely busy/non-busy, does not really mesh at all with a network penetration system that needs to wait for a reply before trying each new password. You'll want it based on QObjects. I'll modify my other answer to show how you might do it while managing network connections. It's very, very wasteful to waste threads on busy waiting for network answers. You do not want to do that. It will perform poorly.
Your application is I/O bound and could, pretty much, run on one thread without much in the way of undue performance loss. Only if you have a huge network pipe and are testing tens of thousands of accounts at the same time would you need more than one thread. I'm serious.
#include <QCoreApplication>
#include <QTextStream>
#include <QRunnable>
#include <QThreadPool>
#include <QFile>
#include <cstdio>
class Data : public QString {
public:
Data(const QString & str) : QString(str) {}
};
class Worker : public QRunnable {
QTextStream m_out;
Data m_data;
public:
void run() {
// Let's pretend we do something serious with our data here
m_out << "(" << this << ") " << m_data << endl;
}
Worker(const Data & data) : m_out(stdout), m_data(data) {}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QThreadPool * pool = QThreadPool::globalInstance();
QFile file("file.txt");
file.open(QIODevice::ReadOnly | QIODevice::Text);
while (! file.atEnd()) {
const Data data(file.readLine());
Worker * worker = new Worker(data);
pool->start(worker);
}
file.close();
pool->waitForDone();
}

Related

Thread safety of emitting Qt signals

I'm using QtConcurrent::run (I know other APIs of QtConcurrent has built in support for progress reporting but I can't use them for other reasons). to run an operation inside a different than the main GUI thread. I also need this operation to notify the GUI thread of the progress made. So what I did is that created a separate function for the operation I want which accepts a callback that carries the information about the progress of the operation. This callback then calls the signal on a QObject living in the main thread.
Here is a full working example that shows my structure:
#include <QCoreApplication>
#include <QObject>
#include <QThread>
#include <QtConcurrent/QtConcurrent>
namespace Operations {
template<typename Callback>
void longOperation(Callback progressCallback)
{
qint64 sum = 0;
for(int i = 0; i < 100; ++i){
QThread::msleep(400);
sum += i;
progressCallback(i/100.0);
}
}
}
class Emitter : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE void doSomething()
{
auto progressCallback = [&](qreal p){
emit progress(p);
};
auto lambda = [progressCallback](){
Operations::longOperation(progressCallback);
};
QtConcurrent::run(lambda);
}
signals:
void progress(qreal);
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Emitter emitter;
QObject::connect(&emitter, &Emitter::progress, [](qreal progress){
qDebug() << "Progress" << progress;
});
emitter.doSomething();
return a.exec();
}
#include "main.moc"
Now my question is using the progressCallback as defined above thread safe? The callback will clearly be triggered from a thread different than the GUI thread, so effectively it's calling emitter.progress() directly on the QObject.
Ok, so I now realised that the code above may not be thread safe. Part of my confusion was what does the emit keyword actually does. It turns out it's actually not much at all. So calling the signal from another thread is not really the best idea.
Instead, one of way of improve the situation is replace the progressCallback with:
auto progressCallback = [&](qreal p){
QMetaObject::invokeMethod(this, [this, p](){ emit progress(p);}, Qt::QueuedConnection);
};
This way the signal is emitted on the thread where the Emitter lives as the lambda slot will be executed "when control returns to the event loop of the receiver's thread" as per the Qt documentation.

Qt, multiple threads, QFuture,Watcher, setting up and getting results

I am trying to perform multiple long-running initializers on threads. I would like to get results as soon as they are available, regardless of order.
I have tried with a simple thread but got stuck where I needed to create multiple threads... and manage them... And the idea of thread pool, futures, thread watcher kept coming up in my research. So, this is my latest try:
struct Initializers {
BigObject *newBigObject;
bool newValue;
int initValue;
};
class BigObject {
public:
BigObject(QString) {}
void initialize(bool, int) {}
};
class MyClass : public QObject {
Q_OBJECT
public:
MyClass() {
connect(&m_futureWatcher, SIGNAL(resultReadyAt(int)), this, SLOT(initUsingFutureSlot(int)));
connect(&m_futureWatcher, SIGNAL(finished()), this, SLOT(initUsingFutureSlot()));
}
void doImportantWork(QStringList someNames);
private slots:
void initUsingFutureSlot(int);
void initUsingFutureSlot();
private:
void createThreadConnections();
//void initComplete(BigObject *);
QFutureWatcher<void> m_futureWatcher;
QVector<Initializers> m_initializersVector;
};
void longInitializer(Initializers &initializers) {
qDebug() << "Running in thread" << QThread::currentThreadId();
initializers.newBigObject->initialize(initializers.newValue, initializers.initValue);
}
void MyClass::doImportantWork(QStringList someNames) {
qDebug() << QString("Long running process using %1 thread(s)").arg(QThread::idealThreadCount());
// Prepare the vector.
foreach (QString someName, someNames) {
BigObject *newBigObject = new BigObject(someName);
Initializers initializers;
initializers.newBigObject = newBigObject;
initializers.newValue = m_appValue;
initializers.initValue = m_appInit;
m_initializersVector.append(initializers);
}
// Start the work
m_futureWatcher.setFuture(QtConcurrent::map(m_initializersVector, longInitializer));
//m_futureWatcher.waitForFinished();
}
// This does not get called
void MyClass::initUsingFutureSlot(int index) {
qDebug() << "Finished" << index;
//initComplete(m_initializersVector.at(index).newBigObject);
}
// This does not get called
void MyClass::initUsingFutureSlot() {
qDebug() << "Finished"
}
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyClass task;
task.doImportantWork(QStringList() << "Hello" << "World");
return app.exec();
}
This version of my code is based on QT5 Tutorial QProgressDialog with QtConcurrent which is the only complete example I was able to find that works with multiple threads.
One problem - their QFutureWatcher's type is void - and I could not find any way to modify the code to use a different type - and not give compile errors. That is why I made the vector they use a class member, to grab the values from there.
My understanding is that the vector gets the slot applied to every member of it - based on documentation.
So, I ran it, but nothing happens. The debug message shows that the threads are running. But the resultReadyAt or finished and their corresponding slots are not called. In addition, closing the program says QThread: Destroyed while thread is still running, so they don't finish and close, as I expected them being handled by the Watcher.
I can make things work with QtConcurrent::run !!!!
I am stuck.
Questions:
How can I make this QFuture / QFutureWatcher work ? What am I missing in my code or what am I doing wrong to make the threads not finish ?
How can I make the template non-void (to retrieve results easier ?)
I have m_futureWatcher.waitForFinished(); commented because that would block the GUI thread, I think - is that correct ?
Is there a better option to run multiple threads ? the word ThreadPool comes to mind but I have seen no examples that I can use - that can notify of completion. I did find a nice example to emulate a ThreadPool (NetResultsIT), but I expect Qt should have something functional.
When closing program, I get QThread: Destroyed while thread is still running. I was under the assumption that threads are closed when done, how should I clean up ? Is deleting the watcher enough ?
I am so lost, fighting these threads for over a week, and they're winning :( Thank you for any help or example.
Using Qt 5.15
Here is a simple example how QThreadPool works
#include <QThreadPool>
#include <QDebug>
#include <QApplication>
#include <QRunnable>
class MyRunnable : public QRunnable
{
public:
MyRunnable():QRunnable(){}
void run(){
for(int i = 0; i < 3; i++)
qDebug() << QThread::currentThreadId() << " i " << i;
}
};
int main(int argc, char *argv[]){
QApplication a(argc, argv);
QThreadPool::globalInstance()->start(new MyRunnable);
QThreadPool::globalInstance()->start(new MyRunnable);
QThreadPool::globalInstance()->start(new MyRunnable);
return 0;
}
output:
0x32c0 i 0
0x32f8 i 0
0x32f8 i 1
0x32f8 i 2
0x32c0 i 1
0x32c0 i 2
0x25a0 i 0
0x25a0 i 1
0x25a0 i 2

Is it safe to delete a heap allocated object inside a slot across different threads?

I am trying to analyse a segfault that seems to occur when accessing a heap allocated object created by a sender thread and accessed by a receiver thread.
Here is a short version of the code :
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include <QTimer>
class Data
{
public:
Data(int data1) : m_data1(data1) {}
int data1() {
return m_data1;
}
private:
int m_data1;
};
class Sender : public QObject
{
Q_OBJECT
public:
Sender(int timeout) : m_timeout(timeout) {}
public slots:
void startSendingDatas() {
QTimer::singleShot(m_timeout, [this]() {
emit datas(new Data(3));
});
}
signals:
void datas(Data *data);
private:
int m_timeout;
};
class Receiver : public QObject
{
Q_OBJECT
public slots:
void onDatas(Data *data) {
qDebug() << "data1 = " << data->data1();
delete data; // is it always safe ?
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Sender sender(5000);
Receiver receiver;
QObject::connect(&sender, SIGNAL(datas(Data*)),
&receiver, SLOT(onDatas(Data*)));
QThread worker;
worker.start();
sender.moveToThread(&worker);
// now we call it asynchronously
QMetaObject::invokeMethod(&sender, "startSendingDatas");
return a.exec();
}
#include "main.moc"
Data does not inherits from QObject so deleteLater is not an option here but is it really safe to do that ?
Thank you.
Yes it is 'safe' to do so if you can garantee that the pointer will still be valid when you`ll access it.
In this simple example that seems the case. I see a potential issue in your code that might be the cause of your random crash :
Event driven objects may only be used in a single thread. Specifically, this applies to the timer mechanism and the network module. For example, you cannot start a timer or connect a socket in a thread that is not the object's thread.
from https://doc.qt.io/qt-5/threads-qobject.html paragraph Object reentrancy.
This is what you are doing : sender object is created on the main thread and on so the timer is started on this thread, then it is moved to the worker thread.
Another thing that I am not 100% confident about : you perform the connection before moving the object to the other thread. By default if nothing is said about the connection, when two objects are on the same thread, it is a direct connection, and when object are on different thread, it´s obviously a queued connection. I don´t know to which extend Qt is robust to changing the connection type when an object is moved, but I would rather first move the object and then connect it.

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.

QEventLoop for synchronous wait for signal

I'm using Qt5, QCoreApplication.
In order to allow for readable and easy to maintain code, I need to write a blocking method in a class/thread A that will emit a signal, connected to a slot in a different thread B, and then wait for an answer or a timeout to occur asynchronously in thread B.
I have first been thinking about what felt like a natural solution: let thread B reply with a signal connected to a slot in thread A, and somehow wait for it. It seems QEventLoop can do that for me. But I keep reading contradictory statements: that's the pattern but avoid it if you can :-).
I'm pretty sure I could achieve my purpose by blocking A on a 0 QSemaphore that B would release when ready. The code would probably not be much more complex that way.
What do you experienced Qt developers think?
Is there a good solution or do you find some symptoms of flawed analysis in my description (i.e. do you think I should never ever need to do something like that? :-))?
The key ingredient you can leverage is the Qt::BlockingQueuedConnection.
This connection type lets you pass return value from a slot. You can use it in a signal-slot connection. You can also directly invoke the slot without using a signal through the QMetaMethod::invoke / QMetaObject::invokeMethod mechanism.
#include <QDebug>
#include <QThread>
#include <QCoreApplication>
class Master : public QObject {
Q_OBJECT
public:
Q_SIGNAL bool mySignal();
Q_SLOT void process() {
if (mySignal()) { // this can be a blocking call
qDebug() << "success!";
}
thread()->quit();
}
};
class Slave : public QObject {
Q_OBJECT
public:
Q_SLOT bool mySlot() {
// do whatever processing is needed here
// It's OK to call QCoreApplication::processEvents here
return true;
}
};
int main(int argc, char** argv) {
QCoreApplication app(argc, argv);
QThread masterThread, slaveThread;
Master master;
Slave slave;
master.moveToThread(&masterThread);
slave.moveToThread(&slaveThread);
slave.connect(&master, SIGNAL(mySignal()), SLOT(mySlot()),
Qt::BlockingQueuedConnection);
masterThread.start();
slaveThread.start();
QMetaObject::invokeMethod(&master, "process");
masterThread.wait();
slaveThread.quit();
slaveThread.wait();
return 0;
}
#include "main.moc"
if you just want to emit a signal in your thread, which means your main thread will have a slot to connect you thread signal, it is simple, just emit it.
but if you want a slot in your thread, and receive signal and so something in your thread, you have to use QEventloop in you run method.
usually, I will just use QThread::wait to wait for other thread end.
be careful here, some Qt objects cannot work across the thread like QSql* and QTcpSocket....