How to start a timer inside QThread?

I would like to start a timer inside QThread. I wrote code in which I get some runtime error. Please guide me in the right direction. What am I doing wrong?

(Parent is QThread(0x1498d10), parent thread is QThread(0x11272b0), current thread is QThread(0x1498d10) 

mainwindow.h // main .h file

 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "mythread.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); MyThread *myt; private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H 

mainwindow.cpp // main .cpp file

 #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); myt=new MyThread(); myt->start(); MainWindow w; } MainWindow::~MainWindow() { delete ui; } 

mythread.h // class for the thread

 #ifndef MYTHREAD_H #define MYTHREAD_H #include <QThread> #include <QTimer> class MyThread:public QThread { public: MyThread(); void run(); QTimer *thr; public slots: void slo(); }; #endif // MYTHREAD_H 

mythread.cpp

 #include "mythread.h" MyThread::MyThread() { thr= new QTimer(); connect(thr,SIGNAL(timeout()),this,SLOT(slo())); } void MyThread::run() { thr->start(1000); } void MyThread::slo() { int i,j=0; i=i+j; } 
+4
source share
3 answers

Just my humble opinion. Don't add a QThread subclass anymore when you don't need it.

I think you just want to run your class in a new thread, or most likely you don't want to block other tasks. Your class is not the thread itself. A subclass basically means that your class is what you subclass.

In other words: Let QThread do its job and concentrate on its class to do what it should do.

Example: MyClass itself does not know anything about threads. He just does what he has to. Increasing the value and displaying the results (plus part of the sleep to show how it can block other functions or gui)

Header file

 #include <QTimer> #include <QObject> class MyClass : public QObject { Q_OBJECT public: explicit MyClass(bool willSleep, QString name, QObject *parent = 0); public slots: void updateCount(); private: QTimer *timer; int count; bool m_wantToSleep; }; 

Implementation

 #include "myclass.h" #include <QDebug> MyClass::MyClass(bool wantToSleep, QString name, QObject *parent) : QObject(parent) { this->setObjectName(name); m_wantToSleep = wantToSleep; count = 0; timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(updateCount())); timer->start(100); } void MyClass::updateCount() { ++count; qDebug() << objectName() << " count: " << count; if (m_wantToSleep) sleep(1); } 

We have code that does this work.

Now implement more threads - this is very simple (memory management, etc. is not handled by a simple example)

 #include "mainwindow.h" #include "ui_mainwindow.h" #include <QThread> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QThread *thread1 = new QThread; // First thread QThread *thread2 = new QThread; // Second thread thread1->start(); thread2->start(); MyClass *myClass = new MyClass(false, "normal class"); MyClass *mySleepClass = new MyClass(true, "sleeper class"); // Better to implement start slot to start timer ( not implemented ) // connect(thread1, SIGNAL(started), myClass, SLOT(start())); // but this suffice, because timer will emit first signal after class is moved to another thred //mySleepClass->moveToThread(thread1); //myClass->moveToThread(thread1); } MainWindow::~MainWindow() { delete ui; } 

Now we can play with threads:

GUI lock (of course we don't want this)

The original example works without using new threads. Objects are in the current thread and why the GUI will be blocked. (since I use the sleep function in one instance)

 //mySleepClass->moveToThread(thread1); //myClass->moveToThread(thread1); 

Non-blocking GUI

We have two more threads. Why not use them. In the example, QThreads are already running, but they are not playing anything. Move our instances there to ensure that the main loop where the GUI lives will no longer be blocked.

Magic function moveToThread

Uncomment the lines and you will see that the graphical interface will not be blocked. Both instances are in the new thread. But then again, there is a sleep function, so you need to count faster than others. But this is not so. Because they block each other. They are in the same thread.

 mySleepClass->moveToThread(thread1); myClass->moveToThread(thread1); 

The results in both previous cases should be: (the instances live in the same thread and have the same event loop, so they block each other)

 "normal class" count: 1 "sleeper class" count: 1 "normal class" count: 2 "sleeper class" count: 2 "normal class" count: 3 "sleeper class" count: 3 

So move them to a separate thread

Now the GUI is not locked, niether instances of each other.

 mySleepClass->moveToThread(thread1); myClass->moveToThread(thread2); 

The results should be: (and the GUI should not be blocked)

 "sleeper class" count: 1 "normal class" count: 1 "normal class" count: 2 "normal class" count: 3 "normal class" count: 4 "normal class" count: 5 

Hope this was clear . For me, this is a more logical approach than subclasses.

Of course, you can create QThread in MyClass , there is no need to create it on top of MyClass, I just wanted to show that you can create one thread and move more instances there.

For everyone who disagrees, I just wanted to say that: MyClass works with thread support : MyClass is a thread with counter capabilities :)

+7
source

Your timer does not belong to your thread. You must create it in your run () method, or you must call tmer-> moveToThread before connecting it to the slots, but after starting the thread.

Note: MyThread belongs to your main topic. You create a timer in the MyThread constructor, so the timer also applies to the main thread. But you are trying to initialize and use it in :: run, which belongs to another thread.

+6
source

To do this, you need to have an event loop in your thread.

From QTimer man page :

In multi-threaded applications, you can use QTimer in any thread that has an event loop. To start the event loop from a thread other than the GUI, use QThread :: exec (). Qt uses the affinity of the timer thread to determine which thread will emit the timeout signal (). Because of this, you must start and stop the timer in your thread; Cannot start timer from another thread.

From the QThread man page :

int QThread::exec () [protected]

Enters an event loop and waits for exit () to be called, returning the value passed to exit (). The return value is 0 if exit () is called via quit (). To start event processing, you must call this function.

In addition, you need to have Q_OBJECT in your class:

 class MyThread:public QThread { Q_OBJECT 

And finally, as Dmitry noted, you need to create a QTimer inside your stream, so the whole cpp file should look like this:

 #include "mythread.h" MyThread::MyThread() { } void MyThread::run() { thr= new QTimer(); connect(thr,SIGNAL(timeout()),this,SLOT(slo())); thr->start(1000); exec(); } void MyThread::slo() { int i = 0,j=0; i=i+j; } 

Also read this document .

+3
source

All Articles