C++ 在 QThread 中启动 QTimer
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10492480/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Starting QTimer In A QThread
提问by Tudor Pascu
I am trying to start a QTimer in a specific thread. However, the timer does not seem to execute and nothing is printing out. Is it something to do with the timer, the slot or the thread?
我正在尝试在特定线程中启动 QTimer。但是,计时器似乎没有执行,也没有打印出任何内容。它与计时器、插槽或线程有关吗?
main.cpp
主程序
#include "MyThread.h"
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
MyThread t;
t.start();
while(1);
}
MyThread.h
我的线程
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QTimer>
#include <QThread>
#include <iostream>
class MyThread : public QThread {
Q_OBJECT
public:
MyThread();
public slots:
void doIt();
protected:
void run();
};
#endif /* MYTHREAD_H */
MyThread.cpp
我的线程.cpp
#include "MyThread.h"
using namespace std;
MyThread::MyThread() {
moveToThread(this);
}
void MyThread::run() {
QTimer* timer = new QTimer(this);
timer->setInterval(1);
timer->connect(timer, SIGNAL(timeout()), this, SLOT(doIt()));
timer->start();
}
void MyThread::doIt(){
cout << "it works";
}
回答by UmNyobe
As I commented (further information in the link) you are doing it wrong :
正如我所评论的(链接中的更多信息),您做错了:
- You are mixing the object holding thread data with another object (responsible of
doIt()
). They should be separated. - There is no need to subclass
QThread
in your case. Worse, you are overriding therun
method without any consideration of what it was doing.
- 您正在将保存线程数据的对象与另一个对象(负责
doIt()
)混合在一起。他们应该分开。 QThread
在您的情况下无需子类化。更糟糕的是,您在run
没有考虑它在做什么的情况下覆盖了该方法。
This portion of code should be enough
这部分代码应该够了
QThread* somethread = new QThread(this);
QTimer* timer = new QTimer(0); //parent must be null
timer->setInterval(1);
timer->moveToThread(somethread);
//connect what you want
somethread->start();
Now (Qt version >= 4.7) by default QThread
starts a event loop in his run()
method. In order to run inside a thread, you just need to move the object. Read the doc...
现在(Qt 版本 >= 4.7)默认QThread
在他的run()
方法中启动一个事件循环。为了在线程内运行,您只需要移动对象。阅读文档...
回答by Andreas Haferburg
m_thread = new QThread(this);
QTimer* timer = new QTimer(0); // _not_ this!
timer->setInterval(1);
timer->moveToThread(m_thread);
// Use a direct connection to whoever does the work in order
// to make sure that doIt() is called from m_thread.
worker->connect(timer, SIGNAL(timeout()), SLOT(doIt()), Qt::DirectConnection);
// Make sure the timer gets started from m_thread.
timer->connect(m_thread, SIGNAL(started()), SLOT(start()));
m_thread->start();
回答by Brian Roach
A QTimer
only works in a thread that has an event loop.
AQTimer
仅适用于具有事件循环的线程。
http://qt-project.org/doc/qt-4.8/QTimer.html
http://qt-project.org/doc/qt-4.8/QTimer.html
In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.
在多线程应用程序中,您可以在任何具有事件循环的线程中使用 QTimer。要从非 GUI 线程启动事件循环,请使用 QThread::exec()。Qt 使用计时器的线程关联来确定哪个线程将发出 timeout() 信号。因此,您必须在其线程中启动和停止计时器;不可能从另一个线程启动计时器。
回答by pathaleswar
You can use the emit signal and start the timer inside the emitted slot function
您可以使用发射信号并在发射槽函数内启动计时器
main.cpp
主程序
#include "MyThread.h"
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
MyThread t;
t.start();
while(1);
}
MyThread.h
我的线程
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QTimer>
#include <QThread>
#include <iostream>
class MyThread : public QThread {
Q_OBJECT
public:
MyThread();
QTimer *mTimer;
signals:
start_timer();
public slots:
void doIt();
void slot_timer_start();
protected:
void run();
};
#endif /* MYTHREAD_H */
MyThread.cpp
我的线程.cpp
#include "MyThread.h"
using namespace std;
MyThread::MyThread() {
mTimer = new QTimer(this);
connect(this,SIGNAL(start_timer()),this, SLOT(slot_timer_start()));
connect(mTimer,SIGNAL(timeout()),this,SLOT(doIt()));
}
void MyThread::run() {
emit(start_timer());
exec();
}
void MyThread::doIt(){
cout << "it works";
}
void MyThread::slot_timer_start(){
mTimer->start(1000);
}
回答by EnjoysMath
You need an event loop to have timers. Here's how I solved the same problem with my code:
您需要一个事件循环来拥有计时器。这是我如何用我的代码解决同样的问题:
MyThread::MyThread() {
}
void MyThread::run() {
QTimer* timer = new QTimer(this);
timer->setInterval(1);
timer->connect(timer, SIGNAL(timeout()), this, SLOT(doIt()));
timer->start();
/* Here: */
exec(); // Starts Qt event loop and stays there
// Which means you can't have a while(true) loop inside doIt()
// which instead will get called every 1 ms by your init code above.
}
void MyThread::doIt(){
cout << "it works";
}
Here's the relevant piece of the documentation that none of the other posters mentioned:
这是其他海报都没有提到的相关文档:
int QCoreApplication::exec()
Enters the main event loop and waits until exit() is called. Returns the value that was set to exit() (which is 0 if exit() is called via quit()). It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets. To make your application perform idle processing (i.e. executing a special function whenever there are no pending events), use a QTimer with 0 timeout. More advanced idle processing schemes can be achieved using processEvents().
int QCoreApplication::exec()
进入主事件循环并等待 exit() 被调用。返回设置为 exit() 的值(如果 exit() 通过 quit() 调用,则为 0)。需要调用这个函数来启动事件处理。主事件循环从窗口系统接收事件并将这些事件分派给应用程序小部件。要使您的应用程序执行空闲处理(即在没有挂起事件时执行特殊功能),请使用超时为 0 的 QTimer。使用 processEvents() 可以实现更高级的空闲处理方案。
回答by Fernando
I have created an example that calls the timer within a lambda function:
我创建了一个在 lambda 函数中调用计时器的示例:
#include <QCoreApplication>
#include <QObject>
#include <QTimer>
#include <QThread>
#include <QDebug>
#include <memory>
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
QThread* thread = new QThread(&app);
QObject::connect(thread, &QThread::started, [=]()
{
qInfo() << "Thread started";
QTimer* timer1 = new QTimer(thread);
timer1->setInterval(100);
QObject::connect(timer1, &QTimer::timeout, [=]()
{
qInfo() << "Timer1 " << QThread::currentThreadId();
});
timer1->start();
});
thread->start();
QTimer timer2(&app);
QObject::connect(&timer2, &QTimer::timeout, [=]()
{
qInfo() << "Timer2 " << QThread::currentThreadId();
});
timer2.setInterval(100);
timer2.start();
return app.exec();
}