QThread and QTimer - c++

I'm working on an application developed with Qt 4.6.
I want to create a custom timer that counts in a separate thread. However, I want this timer to be able to send signals to the main thread.
I subclassed QThread but it doesn't seem to work.
Here is Timer.h:
#ifndef TIMER_H
#define TIMER_H
#include <QtCore/QObject>
#include <QtCore/QThread>
#include <QtCore/QTimer>
class Timer : public QThread
{
Q_OBJECT
public:
explicit Timer(QObject *parent = 0);
~Timer();
// true if the timer is active
bool isCounting();
// start the timer with a number of seconds
void startCounting(int value = 300);
void stopCounting();
// the number of seconds to reach
int maximum();
// the current value of the timer
int value();
// elapsed time since the timer has started
int elapsedTime();
signals:
// sent when the timer finishes to count
void timeout();
// an event is emited at each second when the timer is active
void top(int remainingSeconds);
protected:
// launch the thread
//virtual void run();
private slots:
// decrements the remaining time at each second and emits top()
void timerEvent();
private:
QTimer* _timer;
// remaining time
int _left;
// number of seconds at timer startup
int _maximum;
};
#endif // TIMER_H
And Timer.cpp:
#include "Timer.h"
Timer::Timer(QObject *parent) :
QThread(parent)
{
_timer = new QTimer(this);
_maximum = 0;
_left = 0;
connect(_timer, SIGNAL(timeout()), this, SLOT(timerEvent()));
}
Timer::~Timer()
{
delete _timer;
}
bool Timer::isCounting()
{
// test if timer still active
return _timer->isActive();
}
void Timer::startCounting(int value)
{
qDebug() << QString("Start timer for %1 secs").arg(QString::number(value));
if(_left != 0 || _timer->isActive())
{
_timer->stop();
}
_maximum = value;
_left = value;
// emit the first top
emit top(_left);
// start the timer: 1000 msecs
_timer->start(1000);
// start the thread
start();
}
void Timer::stopCounting()
{
qDebug() << QString("Stopping timer at %1 secs => %2 secs remaining.").arg(QString::number(elapsedTime()), QString::number(_left));
// stop timer
_timer->stop();
_left = 0;
_maximum = 0;
// kill thread
terminate();
}
int Timer::maximum()
{
return _maximum;
}
int Timer::value()
{
return _left;
}
void Timer::timerEvent()
{
qDebug() << "Timer event";
if(--_left == 0)
{
// stop timer
_timer->stop();
// emit end of timer
emit timeout();
// stop thread
terminate();
}
else
{
// emit a signal at each second
emit top(_left);
}
}
int Timer::elapsedTime()
{
return (_maximum - _left);
}
EDIT
I realized the object I tried to move to another thread was actually a singleton. It could lead to a problem (see here).

You don't need to subclass QThread in this particular case. And in general, abstain from subclassing QThread unless you are sure it is what you need.
Here is a quick example how to setup a worker and timer in a thread and launch it:
the worker class:
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0) : QObject(parent) {}
signals:
void doSomething();
public slots:
void trigger() {
emit doSomething();
}
};
main.cpp
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MainThreadObject o;
QThread *thread = new QThread;
Worker w;
QTimer timer;
timer.setInterval(1000);
timer.moveToThread(thread);
w.moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), &timer, SLOT(start()));
QObject::connect(&w, SIGNAL(doSomething()), &o, SLOT(doSomething()));
QObject::connect(&timer, SIGNAL(timeout()), &w, SLOT(trigger()));
thread->start();
return a.exec();
}
So, we have the MainThreadObject which represents a QObject derived living in the main thread. We create the timer and Worker object, which is just used to wrap a signal and slot to avoid the need of subclassing QThread. The timer is setup and it and the worker are moved to the new thread, the thread started() signal is connected to the timer start() slot, the worker doSomething() signal is connected to the main thread object doSomething() slot, and finally the timer timeout() signal is connected to the worker trigger() slot. Then the thread is started which initiates the entire chain in the event loop.
As a result, the MainThreadObject::doSomething() is called every second, with the signal emitted from the secondary thread.

Try
QMetaObject::invokeMethod(&timer, "start", Qt::QueuedConnection); //timer->start()
if you want to start timer immediately
Or
QMetaObject::invokeMethod(&timer, "start", Qt::QueuedConnection , Q_ARG(int, 1000 )); //timer->start(200)
if you want to start timer after 1000s
In the Non-GUI thread (QThread or Pthread Callback)

First, if you subclass from QThread, you have to implement run() method, if not, there is no point of doing that, you can inherit from QObject instead.
Second, your QTimer has to reside in a thread that runs an event loop. Without an event loop no Qt queued signals can be transmitted. You can launch an event loop by calling exec() in thread's run method:
void Timer::run() {
exec();
}

Probable reason can be, your timer object is not in a thread with event loop. Event loop is required to trigger the signals.
However, I would suggest that you should not go with this approach. Timers use different mechanism on different platform and your code might not behave as expected on different platform.

Related

Should I call processEvents() on a thread?

QThread documentation suggests two ways to make code run in a separate thread. If I use moveToThread approach, I have to call processEvents() to issue the timeouts, to have the lambda executed. And this seems to cost a lot of CPU. Why is so?
class Worker : public QObject
{
Q_OBJECT
QTimer* timer;
bool m_abort = false;
public:
Worker() {}
void abort() {m_abort = true;}
public slots:
void run() {
timer = new QTimer;
connect(timer, &QTimer::timeout, []{qDebug() << "computed";});
timer->start(1000);
forever {
if (m_abort) break;
QCoreApplication::processEvents();
}
}
};
class MainWidget : public QWidget
{
Q_OBJECT
QThread thread;
Worker* worker;
public:
MainWidget()
{
worker = new Worker;
worker->moveToThread(&thread);
connect(this, &MainWidget::start, worker, &Worker::run);
thread.start();
emit start();
}
~MainWidget(){worker->abort(); thread.quit(); thread.wait();}
signals:
void start();
};
However if I subclass QThread and reimplement run() it's not necessary to call processEvents. And CPU cost seems lower. Why?
class Worker : public QThread
{
public:
Worker() {}
protected:
void run() override {
QTimer timer;
connect(&timer, &QTimer::timeout, []{qDebug() << "computed";});
timer.start(1000);
exec();
}
};
class MainWidget : public QWidget
{
Q_OBJECT
Worker* worker;
public:
MainWidget()
{
worker = new Worker;
worker->start();
}
};
your run() function 'blocks' the thread. It is being invoked in the thread context, but never returns. This means, the event loop in the thread doesn't get executed anymore as soon as your run() funtion is called.
For the timer events to call your lambdas, the event loop has to be processed.
If you would modify your run function like this:
void run() {
timer = new QTimer(this);
connect(timer, &QTimer::timeout, []{qDebug() << "computed";});
timer->start(1000);
// don't loop here, instead exit the function
// and let the thread return back to the event loop
}
then your lambdas should get called. The thread will also keep running until you call thread.quit()
note: you can also connect directly to the '''started''' signal of the thread:
connect(&thread, &QThread::started, worker, &Worker::run);
thread.start();
moveToThread approach might be improved by calling run() function just after thread emit started.
But I still don't know why the way I put it initially doesn't work.

Custom function interrupt

Is it possible to implement function interrupt in Qt (5.x).
For example if I have a button and want something to execute on the thread (which is running infinite loop) when this button is clicked, I could say something like this:
in thread...
forever
{
if(button_is_pressed_flag)
{
do something...
}
}
is there a better way?
The infinite loop should be an event loop, and then it can automatically process cross-thread slot calls without you worrying about the details.
The idiom to run code "continuously" on an event loop is the zero-duration timer.
Let's say you start with code that looks like this:
class MyThread : public QThread {
bool button_is_clicked_flag = false;
void run() override {
forever{
if (button_is_clicked_flag) {
onButtonClick();
button_is_clicked_flag = false;
}
doWork();
}
}
void onButtonClick();
void doWork();
public:
using QThread::QThread;
void setButtonClickedFlag();
}
int main(int argc, char **argv) {
...
MyThread t;
t.start();
...
}
It is required for doWork() not to take too long - nor too short. If it took ~5ms on modern hardware, it'd be just about a right tradeoff between overhead and latency for a general-purpose application. If you need lower latency reaction in the worker thread, then doWork() must do less work. It probably doesn't make much sense for doWork() to take much less than 1ms.
And whenever doWork() doesn't have anything to do, e.g. if it's done with the computation it was supposed to perform, it should stop the timer that keeps it alive.
You should transform it to look as follows:
class MyWorker : public QObject {
Q_OBJECT
QBasicTimer m_timer;
void doWork();
void timerEvent(QTimerEvent *event) {
if (event->timerId() == m_timer.timerId())
doWork();
}
public:
explicit MyWorker(QObject *parent = nullptr) : QObject(parent) {
m_timer.start(0, this);
}
Q_SLOT void onButtonClick() {
// Ensure we're invoked correctly
Q_ASSERT(QThread::currentThread() == thread());
...
}
}
class Window : public QWidget {
Ui::Window ui;
public:
Q_SIGNAL void buttonClicked();
explicit Window(QWidget *parent = nullptr) : QWidget(parent) {
ui.setupUi(this);
connect(ui.button, &QPushButton::clicked, this, &Window::buttonClicked);
}
};
class SafeThread : public QThread {
Q_OBJECT
using QThread::run; // final method
public:
~SafeThread() { quit(); wait(); } // we're safe to destroy - always
};
int main(int argc, char **argv) {
...
MyWorker worker;
SafeThread thread;
Window window;
// onButtonClick will be executed in worker->thread()
connect(&window, &Window::buttonClicked, &worker, &MyWorker::onButtonClick);
worker.moveToThread(&thread);
thread.start();
window.show();
return app.exec();
}
The event loop that runs in QThread::run will continuously invoke doWork via the timer event handler. But whenever a cross-thread slot call needs to be made to an object living in that thread, the event loop will deliver the internal QMetaCallEvent representing the slot call to QObject::event, which will then execute the call.
Thus, when you set a breakpoint in onButtonClick, there will be QObject::event nearby on the call stack.
You could start a thread and then immediately wait on a std::condition_variable, then when the button is clicked (the event being called on the main thread), notify the condition variable and the thread would awake.
However, this is a bit strange. What are you trying to do? call an asynchronous task upon a button click? In that case, perhaps it would be better just to start one from the button click event with std::packaged_task or std::async.

Qt blocked event loop

I recently started using the QT framework. Yesterday I began programming a simple multithreaded application. At the moment I'm somewhat stuck on the following problem.
Consider two worker classes that both use a thread to do some 'heavy computations'. The first class, FooWorker, looks like the following:
class FooWorker : public QObject
{
Q_OBJECT
public:
FooWorker() : QObject() { }
~FooWorker() { }
signals:
void notify(int);
void aborted();
public slots:
void doWork()
{
int counter = 0;
forever {
// For the sake of this example this reassembles a heavy computational process
if(counter++ < 10) {
emit notify(counter);
QThread::sleep(1);
} else {
counter = 0;
// Wait until we get a signal to restart the process
mutex_.lock();
condition_.wait(&mutex_);
mutex_.unlock();
}
// We should check for a cancellation flag every iteration...
}
emit aborted();
}
private:
QMutex mutex_;
QWaitCondition condition_;
};
The slot 'doWork' will be scheduled to run in another thread. The slot will run forever and is emitting a signal every second until 10 notifications are emitted. After that we wait until it is woken up again.
The second class, BarWorker, looks like this:
class BarWorker : public QObject
{
Q_OBJECT
public:
BarWorker() : QObject() { }
~BarWorker() { }
signals:
void aborted();
public slots:
void doWork()
{
forever {
// Another heavy computational process
QThread::sleep(1);
// We should check for a cancellation flag every iteration...
}
emit aborted();
}
void onNotify(int value)
{
qDebug() << "Notification value:" << value;
}
};
Again the slot 'doWork' will be scheduled to run in another thread. The slot will run forever to do a heavy computational process. Again once the process is done we will wait until it is woken up again (for the sake of this example I left that out in this class).
Finally the main looks like the following:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QThread* barThread = new QThread();
BarWorker* barWorker = new BarWorker();
barWorker->moveToThread(barThread);
QThread* fooThread = new QThread();
FooWorker* fooWorker = new FooWorker();
fooWorker->moveToThread(fooThread);
// Automatically deletes worker and thread
QObject::connect(fooThread, SIGNAL(started()), fooWorker, SLOT(doWork()));
QObject::connect(fooWorker, SIGNAL(aborted()), fooThread, SLOT(quit()));
QObject::connect(fooWorker, SIGNAL(aborted()), fooWorker, SLOT(deleteLater()));
QObject::connect(fooThread, SIGNAL(finished()), fooThread, SLOT(deleteLater()));
QObject::connect(barThread, SIGNAL(started()), barWorker, SLOT(doWork()));
QObject::connect(barWorker, SIGNAL(aborted()), barThread, SLOT(quit()));
QObject::connect(barWorker, SIGNAL(aborted()), barWorker, SLOT(deleteLater()));
QObject::connect(barThread, SIGNAL(finished()), barThread, SLOT(deleteLater()));
QObject::connect(fooWorker, SIGNAL(notify(int)), barWorker, SLOT(onNotify(int)), Qt::QueuedConnection);
fooThread->start();
barThread->start();
return a.exec();
}
When I run the application nothing gets printed. That was to be expected because the event loop of the BarWorker instance is blocked. As the 'notify' signal gets emitted the 'onNotify' slot is queued onto the event queue. Because we have a never ending loop (until we manually abort it) in the 'doWork' slot, the 'onNotify' slot will not be called. To solve this I can do a couple of things, namely:
Connect the 'notify' signal to the 'onNotify' slot by using the Qt::DirectConnection flag. This way it looks like a normal function call executing on the signalling thread.
Occasionally call the QCoreApplication::processEvents() method to force the event queue to be processed.
Unknown solution I do not know at this time :)???
I hope someone has some alternative solution to this problem, or even suggest an entire different approach, because IMHO above solutions are somewhat ugly and do not feel right.
I don't think there is any "magic" solution to be found here; a thread can't be running Qt's event loop if it is running your own custom event loop. In practice, there are two common solutions, which are really two sides of the same coin:
Call processEvents() periodically from your event loop, as you suggested in your question, so that the Qt event-handling code occasionally gets to run and handle incoming asynchronous signals.
Don't have a long-running loop in your doWork() method. Instead, do a short amount of work, store the results/state of that work in a member variable or somewhere, and then call something like QTimer::singleShot(0, this, SLOT(doWork())) so that the Qt event loop will call your doWork() method again soon after the first call to doWork() returns. That way the Qt event loop never gets held off for longer than the (brief) period of time taken up by a single doWork() call.
Of those two options, I think the second is preferable, because it allows the Qt event loop to run in its normal fashion, and it also avoids a potential tripping-over-your-own-shoelaces issue -- e.g. imagine if while using solution (1) your call to processEvents() causes a slot to be called that deletes the BarWorker object. When the processEvents() call returns, BarWorker::doWork() will resume executing, but at that point, all of the local member variables and virtual methods it might access as part of its normal execution have been destroyed, and reading or writing them will cause undefined behavior (if you're lucky, an easy-to-debug crash). That possible snafu can't happen when using solution (2), since if the BarWorker object gets deleted between calls to doWork(), any queued-up asynchronous call to doWork() will be safely cancelled.
The idiom for a forever loop that interoperates with the event loop is a zero-duration timer. We can factor it out into a WorkerBase class, where the unit of work is to be done in the workUnit method:
// https://github.com/KubaO/stackoverflown/tree/master/questions/worker-timer-40369716
#include <QtCore>
// See http://stackoverflow.com/q/40382820/1329652
template <typename Fun> void safe(QObject * obj, Fun && fun) {
Q_ASSERT(obj->thread() || qApp && qApp->thread() == QThread::currentThread());
if (Q_LIKELY(obj->thread() == QThread::currentThread()))
return fun();
struct Event : public QEvent {
using F = typename std::decay<Fun>::type;
F fun;
Event(F && fun) : QEvent(QEvent::None), fun(std::move(fun)) {}
Event(const F & fun) : QEvent(QEvent::None), fun(fun) {}
~Event() { fun(); }
};
QCoreApplication::postEvent(
obj->thread() ? obj : qApp, new Event(std::forward<Fun>(fun)));
}
class WorkerBase : public QObject {
Q_OBJECT
QBasicTimer timer_;
protected:
virtual void workUnit() = 0;
void timerEvent(QTimerEvent *event) override {
if (event->timerId() == timer_.timerId() && timer_.isActive())
workUnit();
}
public:
using QObject::QObject;
Q_SIGNAL void finished();
/// Thread-safe
Q_SLOT void virtual start() {
safe(this, [=]{
timer_.start(0, this);
});
}
/// Thread-safe
Q_SLOT void virtual stop() {
safe(this, [=]{
if (!isActive()) return;
timer_.stop();
emit finished();
});
}
bool isActive() const { return timer_.isActive(); }
~WorkerBase() {
if (isActive()) emit finished();
}
};
The workers then become:
class FooWorker : public WorkerBase
{
Q_OBJECT
int counter = 0;
bool isDone() const { return counter >= 10; }
void workUnit() override {
if (!isDone()) {
counter ++;
emit notify(counter);
QThread::sleep(1);
} else
stop();
}
public:
void start() override {
counter = 0;
WorkerBase::start();
}
void stop() override {
if (!isDone()) emit aborted();
WorkerBase::stop();
}
Q_SIGNAL void notify(int);
Q_SIGNAL void aborted();
};
class BarWorker : public WorkerBase
{
Q_OBJECT
void workUnit() override {
QThread::sleep(1);
}
public:
void stop() override {
emit aborted();
WorkerBase::stop();
}
Q_SIGNAL void aborted();
Q_SLOT void onNotify(int value)
{
qDebug() << "Notification value:" << value;
}
};
Note that the aborted() and finished() signals have different meanings.
Finally, the test harness:
class Thread : public QThread { public: ~Thread() { quit(); wait(); } };
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
BarWorker barWorker;
FooWorker fooWorker;
Thread barThread, fooThread;
barWorker.moveToThread(&barThread);
fooWorker.moveToThread(&fooThread);
barWorker.start();
fooWorker.start();
QObject::connect(&fooWorker, &FooWorker::finished, &app, &QCoreApplication::quit);
QObject::connect(&fooWorker, &FooWorker::notify, &barWorker, &BarWorker::onNotify);
fooThread.start();
barThread.start();
return app.exec();
}
#include "main.moc"
If you get a QBasicTimer::stop: Failed. Possibly trying to stop from a different thread warning, it's of no consequence and is a result of a Qt bug.

create qt thread event loop

I am using Qt in order to write a GUI application.
A main thread is responsible for the GUI and creates an QThread in order to do some work with an object.
class Worker
{
void start() {
QTimer* timer = new Timer();
connect(timer,SIGNAL(timeout()),this,SLOT(do()));
}
void do() {
//do some stuff
emit finished();
}
}
class GUI
{
//do some GUI work then call startWorker();
void startWorker() {
QThread* thread = new Thread();
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(thread, SIGNAL(started()), worker, SLOT(start()));
connect(worker, SIGNAL(finished()), workerthread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
}
}
Now I have several problems:
The timer in my worker class does not work. Maybe it is because the new thread has no event loop, but I have no idea how to create such one. I tried
connect(workerthread, SIGNAL(started()), workerthread, SLOT(exec()));
but it does not work either.
When I try to wait on the new thread, the signal is never sent
class GUI
{
void exit() {
thread->wait();
}
}
I think it also is because there is no event loop and because of that no signal is emitted.
Does anybody have an idea how to solve these problems?
why not use qthreadpool, than you make your task class inherits from qrunnable and qobject, this way you can use signals and slots to pass data from one thread to another, is much simpler to implement, and increase performance from not recreating a thread or having one sleeping all the time
class myTask : public QObject, public QRunnable{
Q_OBJECT
protected:
void run(); //where you actually implement what is supposed to do
signals:
void done(int data);//change int to whatever data type you need
}
//moc click example, or use a timer to call this function every x amount of time
void button_click(){
myTask *task = new myTask();
task->setAutoDelete(true);
connect(task,SIGNAL(done(int)),this,SLOT(after_done(int)),Qt::QueuedConnection);
QThreadPool::globalInstance()->start(task);
}
by default you application gets 1 thread automatically, which you can use to handle the graphic, than use the qthreadpool to process the data/object on demand, you can even set the max amount of threads your application can use to process new request, the others will stay in a queue until one thread is freed
QThreadPool::globalInstance()->setMaxThreadCount(5);
this is a sample code for you :
QThread* thread = new QThread();
Worker* worker = new Worker(3000);
worker->moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), worker, SLOT(start()));
thread->start();`
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(qint32,QObject *parent = 0);
qint32 myTime;
signals:
void workFinished();
public slots:
void doWork();
void start();
private:
QTimer *timer;
};
#include "worker.h"
#include <QTimer>
#include <QDebug>
Worker::Worker(qint32 t,QObject *parent) :
QObject(parent)
{
myTime=t;
}
void Worker::start()
{
timer = new QTimer();
timer->start(myTime);
qDebug()<<QString("start work in time:%1").arg(myTime);
connect(timer,SIGNAL(timeout()),this,SLOT(doWork()));
}
void Worker::doWork()
{
qDebug()<<"dowork";
timer->stop();
emit workFinished();
}
Debug results :
start work in time:3000
I hope this helps you.

QtConcurrent::run emit signal

I would like to emit a signal in Qt, from a function that I called with QtConcurrent::run
Is this possible? It seems like my slot never gets called. All of the signals, slots, and functions are part of the same class object. I have tried making the connection in the Master thread, and in the slave thread. I dont really care if the signal and slot are in the same thread or not, I just want to get it to happen.
Thanks
The below works just fine in Qt 4.8.7. The signal is emitted from the worker thread, and consumed in the main thread. We assert that the slot runs in the main thread, and the functor runs in the worker thread.
// https://github.com/KubaO/stackoverflown/tree/master/questions/concurrent-emit-qt4-7114421
#include <QtCore>
class Helper : public QObject {
Q_OBJECT
public:
int n = 0;
Q_SLOT void increment() {
Q_ASSERT(QThread::currentThread() == qApp->thread());
n++;
}
};
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
Helper helper;
Q_ASSERT(helper.n == 0);
QtConcurrent::run([&]{
Q_ASSERT(QThread::currentThread() != qApp->thread());
QObject src;
QObject::connect(&src, SIGNAL(destroyed(QObject*)), &helper, SLOT(increment()));
QObject::connect(&src, SIGNAL(destroyed(QObject*)), &app, SLOT(quit()));
});
app.exec();
Q_ASSERT(helper.n == 1);
}
#include "main.moc"
In Qt 5, you don't need the helper class to demonstrate that it works:
#include <QtConcurrent>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
int n = 0;
Q_ASSERT(n == 0);
QtConcurrent::run([&]{
Q_ASSERT(QThread::currentThread() != qApp->thread());
QObject src;
QObject::connect(&src, &QObject::destroyed, &app, [&]{
Q_ASSERT(QThread::currentThread() == qApp->thread());
n ++;
qApp->quit();
});
});
app.exec();
Q_ASSERT(n == 1);
}
You can use a Qt::QueuedConnection for that connection (pass it to the connect call which establishes the connection), since the signal will always be emitted from a different thread than the receiver objects thread.
An Qt::AutoConnection will also do the same thing and add the signal to the event queue of the thread of the receiving object.
If the receiving thread is blocked, and thus never reenters the event queue, the signal cannot be received by the slot of the receiving object.
You really should use QFuture and QFutureWatcher with QtConcurrent::run().
yes it is possible.
just look little example:
in this example we want implement multithread. longProcess function go to thread pool and process in thread pool and after that answer of long process function back to main thread.
Test.h
Class Test: public QObject
{
Q_OBJECT
public:
explicit Test(QObject *parent = nullptr);
void resultAvailable();
static void doLongProcess(Test *test);
signals:
void finishedProcess(const QString &massage);
public slots:
void captureSignal(const QString &message);
};
Test.cpp
void Test::resultAvailable()
{
QtConcurrent::run(&ContactsModelManager::doLongProcess, this);
connect(this , &Test::finishedProcess,
this , &Test::captureSignal);
}
//attention!! doLongProcess is static fnuction
void Test::doLongProcess(Test *test)
{
//this process is very long
test->longProcess();
}
void Test::longProcess()
{
//do your process
//at the end emit your signal
emit finishedProcess("finished process in another thread");
}
void Test::captureSignal(const QString &message)
{
Qdebug() << "message is: " << message;
}