Hello everyone,
I'm not really used to using Qt, but for my work, I'v to do with it . I 've tried to make a generic thread Worker for my actions in multithreaded application. Here is my code
ThreadWorker.h
#ifndef _THREADWORKER_H_
#define _THREADWORKER_H_
#include "QtCore/qobject.h"
#include "QtCore/qthread.h"
#include "QtCore/qtimer.h"
class ThreadWorker
: public QObject {
Q_OBJECT
private:
int _frequency;
public:
ThreadWorker(int frequency = 300);
~ThreadWorker();
/*!
\brief Create a worker which call the specified slot in th specified thread
\param thread The thread to use
\param source The object which contains the slot to use
\param slot The slot to use
*/
void createWorker
(QThread *thread,
const QObject* source,
const char *slot);
/*!
\brief Sets the call frequency for the threaded method
\param frequency Frequency in millsecond (default value: 300ms)
*/
void setFrequency(int frequency);
private slots:
void start();
void stop();
public slots:
/*!
\brief a slot to indicates the end of our current work
*/
void terminate();
signals:
void finished();
};
#endif
#ifndef _THREADWORKER_H_
#define _THREADWORKER_H_
#include "QtCore/qobject.h"
#include "QtCore/qthread.h"
#include "QtCore/qtimer.h"
class ThreadWorker : public QObject
{
Q_OBJECT
private:
int _frequency;
QTimer _timer;
public:
ThreadWorker(int frequency = 300);
~ThreadWorker();
/*!
\brief Create a worker which call the specified slot in th specified thread
\param thread The thread to use
\param source The object which contains the slot to use
\param slot The slot to use
*/
void createWorker(QThread *thread, const QObject* source, const char *slot);
/*!
\brief Sets the call frequency for the threaded method
\param frequency Frequency in millsecond (default value: 300ms)
*/
void setFrequency(int frequency);
private slots:
void start();
void stop();
public slots:
/*!
\brief a slot to indicates the end of our current work
*/
void terminate();
signals:
void finished();
};
#endif
To copy to clipboard, switch view to plain text mode
ThreadWorker.cpp
#include "ThreadWorker.h"
ThreadWorker::ThreadWorker(int frequency): _frequency(frequency), _timer(this)
{}
ThreadWorker::~ThreadWorker()
{
terminate();
}
void ThreadWorker
::createWorker(QThread *thread,
const QObject* source,
const char *slot) {
connect(&_timer, SIGNAL(timeout()), source, slot, Qt::DirectConnection);
connect(thread, SIGNAL(started()), this, SLOT(start()), Qt::DirectConnection);
connect(this, SIGNAL(finished()), thread, SLOT(quit()), Qt::DirectConnection);
connect(this, SIGNAL(finished()), this, SLOT(stop()), Qt::DirectConnection);
moveToThread(thread);
}
void ThreadWorker::setFrequency(int frequency)
{
_frequency = frequency;
}
void ThreadWorker::start()
{
_timer.setInterval(_frequency);
_timer.start();
}
void ThreadWorker::stop()
{
if(_timer.isActive())
{
_timer.stop();
}
}
void ThreadWorker::terminate()
{
if(_timer.isActive())
{
emit finished();
}
}
#include "ThreadWorker.h"
ThreadWorker::ThreadWorker(int frequency): _frequency(frequency), _timer(this)
{}
ThreadWorker::~ThreadWorker()
{
terminate();
}
void ThreadWorker::createWorker(QThread *thread, const QObject* source, const char *slot)
{
connect(&_timer, SIGNAL(timeout()), source, slot, Qt::DirectConnection);
connect(thread, SIGNAL(started()), this, SLOT(start()), Qt::DirectConnection);
connect(this, SIGNAL(finished()), thread, SLOT(quit()), Qt::DirectConnection);
connect(this, SIGNAL(finished()), this, SLOT(stop()), Qt::DirectConnection);
moveToThread(thread);
}
void ThreadWorker::setFrequency(int frequency)
{
_frequency = frequency;
}
void ThreadWorker::start()
{
_timer.setInterval(_frequency);
_timer.start();
}
void ThreadWorker::stop()
{
if(_timer.isActive())
{
_timer.stop();
}
}
void ThreadWorker::terminate()
{
if(_timer.isActive())
{
emit finished();
}
}
To copy to clipboard, switch view to plain text mode
And here is the code which use the ThreadWorker
#include "ThreadWorker.h"
{
Q_OBJECT
private
ThreadWorker _worker;
public:
MyObject();
~MyObject();
void start();
void stop();
public slots:
void process();
};
MyObject::MyObject(): _thread(this)
{}
MyObject::~MyObject()
{
if(_thread.isRunning())
{
_worker.terminate();
_thread.wait(500);
}
}
void MyObject::start()
{
if(_thread.isRunning())
{
return;
}
_worker.createWorker(&_thread, this, SLOT(process()));
_thread.start();
}
void MyObject::process()
{
//do something
}
void MyObject::stop()
{
_worker.terminate();
}
#include "ThreadWorker.h"
class MyObject : public QObject
{
Q_OBJECT
private
QThread _thread;
ThreadWorker _worker;
public:
MyObject();
~MyObject();
void start();
void stop();
public slots:
void process();
};
MyObject::MyObject(): _thread(this)
{}
MyObject::~MyObject()
{
if(_thread.isRunning())
{
_worker.terminate();
_thread.wait(500);
}
}
void MyObject::start()
{
if(_thread.isRunning())
{
return;
}
_worker.createWorker(&_thread, this, SLOT(process()));
_thread.start();
}
void MyObject::process()
{
//do something
}
void MyObject::stop()
{
_worker.terminate();
}
To copy to clipboard, switch view to plain text mode
I run this code in unit tests with QTest library and I use the macro QTEST_MAIN.
The execution seems fine until the following error:
Program: …
Module: 4.7.4
File: global\qglobal.cpp
Line:
ASSERT failure in QCoreApplication::sendEvent: “Cannot send events to objects owned by a different thread. Current thread 3f6a90.
Receiver ‘’ (of type ‘ThreadWorker’) was created in thread 12ef5câ€, file kernel\qcoreapplication.cpp, line...
I do not really see where it comes from :/. Only thing is that this does not occur if I do not put this line moveToThread (thread), however, in this case, the slot process() is never called.
Does anyone have any idea what I am doing wrong?
Thank you in advance for any help you can provide me
ps: Sorry if my english is not correct :/
Bookmarks