Deletelater not responding in qt - c++

I am asking this question second time and I did not find a solution that I am not so familiar with qt events.This is my code:
class My_worker :public QObject{};
I have a function in that class that will send data periodically with a timer in it.
My_worker::process{
Qtimer my_timer=new Qtimer();
my_timer->setInterval(time_ms);
connect(my_timer,SIGNAL(timeout()),this(sendData()))
}
So with function sendData() I am sending data with the my_timer elapsed. this is my thread doing the work. I create these in my QCoreapplication class. so:
class My_Application: public QCoreApplication{};
In constructor I define the signals and threaa like this.
My_Application::My_Application{
//First I create an object of My_worker
My_worker my_worker=new My_worker();
//Then I create a thread and move my worker to thread
QThread my_thread=new QThread();
my_worker->moveToThread(my_thread);
// then I connect the signals.
connect(my_thread,SIGNAL(started)),my_worker,SLOT(process())); //So starts processing
connect(my_worker,SIGNAL(finished()),my_thread,SLOT(quit()));
connect(my_thread,SIGNAL(finished()),my_thread,SLOT(deleteLater))));
connect(my_worker,SIGNAL(finished()),my_worker,SLOT(deleteLater()));
}
And finally my dataSend() function is;
void dataSend(){
//do some work
// **if I emit my finished signal here I see that the destructor of my_worker is called**
}
But I dont want to emit the signal here and I want to destruct my_work when my My_Application is finished.
So in My_Application destructor I try to delete my_worker so the destructor is
My_Application::~My_Application(){
cout<<"the destructor called for app"<<endl;
if(my_worker->thread())
connect(my_worker,SIGNAL(destroyed()),my_thread,SLOT(quit()));
my_worker->deleteLater(); // this does not work and does not call my_worker destc.
}

Perhaps this might solve your problem:
class My_worker :public QObject, public QRunnable{
Q_OBJECT
public:
My_Worker() : loop(0) {}
void run();
public slots:
void sendData();
void quit();
private:
QEventLoop *loop;
};
My_Worker.cpp
void My_Worker::run(){
QTimer timer;
timer.setInterval(time_ms);
connect(&timer, SIGNAL(timeout()), this, SLOT(sendData()));
loop = new QEventLoop;
loop->exec();
delete loop;
}
void My_Worker::quit(){
if (loop){
loop->quit();
}
}
My_Application.cpp
My_Application::My_Application(){
My_worker *my_worker=new My_worker();
connect(this, SIGNAL(aboutToQuit()), my_worker, SLOT(quit()));
QThreadPool::globalInstance()->start(my_worker);
}
See the documentation for further information about the QThreadPool, QEventLoop and QRunnable classes.

Related

How do I invalidate canvas of an object owned by another thread?

I want to load data in a separate thread and than to call redraw method to invalidate canvas and draw the data. However, when I call redraw method, it triggers breakpoint with following message:
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by different thread..."
I'm looking for some sort of dispatch method that could be used to call the function in the correct thread.
What is the proper way to do this is Qt5?
The general idea is to send a signal from worker thread back to the main thread which then triggers the redraw. Something like this (I haven't tested it):
class Worker : public QObject
{
Q_OBJECT
public:
...
void loadData()
{
... // Do stuff
emit dataLoaded();
}
}
class MainWindow : public QObject
{
Q_OBJECT
public:
MainWindow()
{
Worker *worker = new Worker;
worker->moveToThread(workerThread);
connect(&workerThread, &QThread::started, worker, &Worker::loadData);
connect(worker, &Worker::dataLoaded, this, &MainWindow::redraw);
workerThread.start();
}
public slots:
void redraw()
{
// Do your redrawing here
}
private:
QThread workerThread;
}

QTimer running in QThread

I need a class with a timer which will do a task every 100msec, this class need to run in a thread, so I would like to combine qtimer with qthread.
I have created the following code:
class Worker : public QObject
{
Q_OBJECT
public:
void setEnabled(bool enable);
public slots:
void initialize();
private:
void doWork();
QTimer *m_timer;
}
void Worker::initialize()
{
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &Worker::doWork, Qt::DirectConnection);
m_timer->start(100);
}
void Worker::setEnabled(bool enable)
{
if(enable)
m_timer->start(100);
else
m_timer->stop();
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc,argv);
QThread *thread = new QThread;
Worker *worker = new Worker;
QObject::connect(thread, &QThread::started, worker, &Worker::initialize);
worker->moveToThread(thread);
thread->start();
app.exec();
delete worker;
delete thread;
}
With the following commands I could then enable/disable the time
worker->setEnabled(false);
worker->setEnabled(true);
I have tested and it works fine, but I would like to know if this is the correct way?
Thanks for the help
No, it's not entirely correct.
Worker::setEnabled(bool enable) should be a slot too, as it's invoking the QTimer::start() slot directly. Calling Worker::setEnabled directly from the main thread then results in undefined behavior. You must use a signal-slot connection to invoke setEnabled safely from the main thread.
You also should have initialized Worker::m_timer in the constructor rather than deferring it until initialize(), so you don't run into a dangling pointer if Worker::setEnabled was invoked earlier than expected. moveToThread will move all children of Worker with it, so that's perfectly sane behavior.
The only thing I need to mention is that the m_timer can't be initialzed in the constructor. See here information from qt:
By the way, one extremely important thing to note here is that you should NEVER allocate heap objects (using new) in the constructor of the QObject class as this allocation is then performed on the main thread and not on the new QThread instance, meaning that the newly created object is then owned by the main thread and not the QThread instance. This will make your code fail to work. Instead, allocate such resources in the main function slot such as initialize() in this case as when that is called the object will be on the new thread instance and thus it will own the resource.

Using QThread and moveToThread properly with QTimer and QTcpSocket

From reading this blog, this blog and some others, Subclassing QThread is bad practice. So I tried to apply this method.
But my problem is that I have a QTimer and a QTcpSocket in the class I want to move to a different thread. Suddenly, it's not as easy as it the examples used. :(
QThread m_commsThread;
m_pICommsHandler = new CommsHandlerIP();
m_pICommsHandler->moveToThread(&m_commsThread);
m_commsThread.start();
And here is the CommsHandlerIP class, methods are not included.
class CommsHandlerIP : public QObject
{
Q_OBJECT
public:
CommsHandlerIP();
~CommsHandlerIP(void);
protected:
QTcpSocket m_TCPSocket;
QTimer m_timer;
}
Issue is that the QTimer and the QTcpSocket (inside CommsHandlerIP class) are in the main thread even if you move CommsHandlerIP. So I can't start the timer or connect the socket.
If I try to moveToThread the QTimer and QTcpSocket (inside the constructor by passing the thread pointer for instance), this become really messy when I leave the app.
What should I do?
Class Instances are created on the calling thread.
QTimer inherits QObject.
Each Thread on Qt can have an event loop if it calls exec().
so you want to move QTimer to an event loop on another thread.
so you should manually move it.
Therefore, delay their creation until after you move the object: -
class CommsHandlerIP : public QObject
{
Q_OBJECT
public slots:
void Initialise();
private:
void Run();
// c++ 11, initialising in headers...
QTimer* m_pTimer = NULL;
QTcpSocket* m_pSocket = NULL;
};
void CommsHandlerIP::Initialise()
{
m_pTimer = new QTimer(this);
m_pSocket = new QTcpSocket(this);
Run();
}
QThread m_commsThread;
m_pICommsHandler = new CommsHandlerIP();
// Note Qt 5 connect style
connect(&m_commsThread, &QThread::started, m_pICommsHandler, &CommsHandlerIP::Initialise);
m_pICommsHandler->moveToThread(&m_commsThread);
m_commsThread.start();
When the thread is started, the CommsHanderIP Initialise function is called; this is where you should create and setup the QTcpSocket and QTimer objects before calling Run(). As the CommsHandlerIP is running in the new thread before creating those objects, they will also share the same thread affinity.
There is a much simpler method of achieving all this that follows the same algorithm but doesn't involve all the boilerplating needed to create threads and changing thread affinities, using QRunnable and QThreadPool
If I convert Merlin069's example, you'll see how it simplifies the code a bit:
class CommsHandlerIP : public QObject, public QRunnable
{
Q_OBJECT
public:
void run();
public slots:
//... any slots
signals:
//... any signals
private:
// c++ 11, initialising in headers...
QTimer* m_pTimer = NULL;
QTcpSocket* m_pSocket = NULL;
};
void CommsHandlerIP::run()
{
m_pTimer = new QTimer();
m_pSocket = new QTcpSocket();
//...
delete m_pTimer;
delete m_pSocket;
}
QThreadPool::globalInstance()->start(new CommsHandlerIP);
I stumbled across this when searching on Timer behaviour and movetoThread.
The accepted answer is a good work-around but not really the root cause of the problem. There is a general rule that when you move an object then all child objects will move as well. So you just need to make sure that the QTimer becomes a child so pass the this pointer in its constructor.
CommsHandlerIPL::CommsHandlerIP()
: QObject(), m_pTimer(new QTimer(this)) // <=== crucial to make it a "child" object
{
}

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.

QThread related problems

I'm having some problems and questions about QThread.
1) When I use QThread->quit(), finished() signal is not emitted..
2) How is right way to build and finish execution of thread?
1) finished signal code - the header file.
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
class MyThread: public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
signals:
public slots:
void finished();
protected:
void run();
};
#endif // MYTHREAD_H
1) CPP file.
#include "MyThread.h"
MyThread::MyThread(QObject *parent) :
QThread(parent)
{
}
void MyThread::finished()
{
//never gets called...
qDebug() << "Finished.";
}
void MyThread::run()
{
connect(this, SIGNAL(finished()), this, SLOT(finished()), Qt::DirectConnection);
this->exec();
}
I'm building it with this:
MyThread *mThread = new MyThread(this); //What does parent do/mean ?
mThread->start();
Sleep(5000); //Windows.
mThread->quit(); //Finish thread.
I even don't understand what Qt::DirectConnection does, I already read documentation, but I don't really get it how and when to use Direct/Queued connections.
Another questions that came to my mind just now.
1) How can I finish and cleanup thread from self? (I mean, thread should quit by itself and do cleanup.)
2) How to proper why of creating/running new thread and why?
Thank you.
Don't sub-class QThread. Instead, create a worker object (that inherits QObject), create a QThread, then call the moveToThread() method on your worker object.
class Worker : public QObject
{
Q_OBJECT
public:
Worker( QObject * parent = 0 )
: QObject( parent )
{
connect( this, SIGNAL(done()), \
this, SLOT(deleteLater())
);
}
public slots:
void doWork() { // work, work }
signals:
void done(); // emit this when you're finished with the work
};
// in your main function (or wherever)
QThread * thread = new QThread();
Worker * w = new Worker();
w->moveToThread( thread );
thread->start();
// clean up your thread
QObject::connect( w, SIGNAL(destroyed()), thread, SLOT(quit()) );
QObject::connect( thread, SIGNAL(finished()), thread(deleteLater()) );
// at some point, emit a signal connected to your workers 'doWork()' slot.
// when the work is finished, the worker and thread will both clean themselves up.
Edit: What if I'm using an older version of Qt?
In recent Qt releases, the default implementation of the QThread::run() method is to call exec(), which starts the thread's event loop. If you're supporting an older version of Qt, you do need to subclass QThread in order for the above code to work.
class MyThread : public QThread
{
void run() { exec(); }
};
Then, just use MyThread instead of QThread, and all of the above still applies. In this case, it makes perfect sense to subclass QThread because you're creating a specialized thread class (one that runs its own event loop when you call start()).
As for thread clean-up, the above still applies.
QObject::connect( thread, SIGNAL(finished()), thread, SLOT(deleteLater()) );
When you call MyThread::quit(), the event loop will return, run() will return, then the thread object emits the finished() signal. Since the MyThread object actually lives in the main event loop, the deleteLater() slot invocation will still be delivered.