Qt: QTimer和QThread
2015-01-12 11:48
344 查看
让QTimer 跑在其他线程. 一般写法如下.
1. 在main thread中为worker thread指定定时器.
需要注意几个地方.
1) QTimer 不能指定parent, 否则 会出现警告 " QObject::moveToThread: Cannot move objects with a parent"
因为moveToThread 无法移动有parent的object.
2) QTimer 需要用moveToThread 来改变线程相关性. 这样emit signal的时候才会在worker线程.
3) connect timeout时, 需要附加参数Qt::DirectConnection,
根据Qt的文档中
connect默认参数为AutoConnection, 所以当slot的object是main线程时, 会自动post 事件到main线程. 指定DirectConnection 才会直接调用slot. 即在worker线程中处理.
4) 如果直接 timer->start(); 的话, 会有警告: QObject::startTimer: Timers can only be used with threads started with QThread
timer 只能在同一个线程中创建和启动. (使用moveToThread 可以修改). 这里写"同一个线程" 似乎描述不太准确. 但大概就是这个意思.
所以需要这样启动.
其实也可以这样取巧:
5) 因为timer 没有指定parent, 所以不会自动销毁.
2. 在worker线程中启动QTimer.
MyClass 是一个UI窗口. 类似如下.
so. 可以看到. 如果timer是在worker 线程中创建的话. 即不需要moveToThread来修改线程相关性.
timer->start()也可以直接调用.
但仍然需要指定 Qt::DirectConnection. 因为timerReceiver 是在main thread中.
如果timerReceiver 也在worker线程中创建, 则不需要指定 Qt::DirectConnection.
看起来和平时用的一模一样. →_→
1. 在main thread中为worker thread指定定时器.
QThread* thread = new QThread(this); thread->start(); QTimer *timer = new QTimer(0); timer->setInterval(100); timer->moveToThread(thread); connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout()), Qt::DirectConnection); connect(thread, SIGNAL(started()), timer,SLOT(start()));
需要注意几个地方.
1) QTimer 不能指定parent, 否则 会出现警告 " QObject::moveToThread: Cannot move objects with a parent"
因为moveToThread 无法移动有parent的object.
2) QTimer 需要用moveToThread 来改变线程相关性. 这样emit signal的时候才会在worker线程.
3) connect timeout时, 需要附加参数Qt::DirectConnection,
根据Qt的文档中
Qt::AutoConnection 0 (default) If the signal is emitted from a different thread than the receiving object, the signal is queued, behaving as Qt::QueuedConnection. Otherwise, the slot is invoked directly, behaving as Qt::DirectConnection. The type of connection is determined when the signal is emitted. Qt::DirectConnection 1 The slot is invoked immediately, when the signal is emitted. Qt::QueuedConnection 2 The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.
connect默认参数为AutoConnection, 所以当slot的object是main线程时, 会自动post 事件到main线程. 指定DirectConnection 才会直接调用slot. 即在worker线程中处理.
4) 如果直接 timer->start(); 的话, 会有警告: QObject::startTimer: Timers can only be used with threads started with QThread
timer 只能在同一个线程中创建和启动. (使用moveToThread 可以修改). 这里写"同一个线程" 似乎描述不太准确. 但大概就是这个意思.
connect(thread, SIGNAL(started()), timer,SLOT(start()));
所以需要这样启动.
其实也可以这样取巧:
QThread* thread = new QThread(this); thread->start(); QTimer *timer = new QTimer(0); timer->setInterval(100); connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout()), Qt::DirectConnection); //connect(thread, SIGNAL(started()), timer,SLOT(start())); timer->start(); timer->moveToThread(thread);
5) 因为timer 没有指定parent, 所以不会自动销毁.
2. 在worker线程中启动QTimer.
class Worker :public QThread { Q_OBJECT public: Worker(MyClass *parent); virtual ~Worker(){} void run(); MyClass *timerReceiver; }; Worker::Worker(MyClass *parent) : QThread(parent) { timerReceiver = parent; } void Worker::run() { QTimer *timer = new QTimer(this); timer->setInterval(100); connect(timer, SIGNAL(timeout()), timerReceiver, SLOT(onTimeout()), Qt::DirectConnection); timer->start(); exec(); return; }
MyClass 是一个UI窗口. 类似如下.
class MyClass : public QMainWindow { Q_OBJECT public: MyClass(QWidget *parent = 0); ~MyClass(); public slots: void onTimeout(); private: Ui::MyClassClass ui; }; MyClass::MyClass(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); Worker *thread = new Worker(this); //QThread* thread = new QThread(this); thread->start(); } MyClass::~MyClass() { } void MyClass::onTimeout() { }
so. 可以看到. 如果timer是在worker 线程中创建的话. 即不需要moveToThread来修改线程相关性.
timer->start()也可以直接调用.
但仍然需要指定 Qt::DirectConnection. 因为timerReceiver 是在main thread中.
如果timerReceiver 也在worker线程中创建, 则不需要指定 Qt::DirectConnection.
void Worker::run() { TestObject *timerReceiver = new TestObject(this); QTimer *timer = new QTimer(this); timer->setInterval(100); connect(timer, SIGNAL(timeout()), timerReceiver, SLOT(onTimeout())); timer->start(); exec(); return; }
class TestObject : public QObject { Q_OBJECT public: TestObject(QObject *parent) : QObject(parent) {} public slots : void onTimeout(){} };
看起来和平时用的一模一样. →_→
相关文章推荐
- Qt之等待提示框(QTimer)
- Qt 线程基础(QThread、QtConcurrent等)
- 解析Qt中QThread使用方法
- Qt之QTimer
- 解析Qt中QThread使用方法
- Qt编程7:Qt定时器 QTimer使用
- QTimer和Qthread的调度时间精度
- Qt 线程基础(QThread、QtConcurrent等)
- 【Qt开发】QThread 实用技巧、误区----但文档中没有提到
- qt的QThread消息归属和MoveToThread的作用
- Qt中利用QThread在线程中同步使用QFtp
- Qt 线程基础(QThread、QtConcurrent等)
- Qt之等待提示框(QTimer)
- [Qt]在不开启事件循环的线程中使用QTimer
- Qt开发者关于QThread的咆哮——你们都用错了
- 浅谈 QT 中的 QTimer、QTimerEvent 与 MFC 中的 OnTimer
- qt2.2 多线程发送消息 QThread::postEvent postEvent qApp->postEvent QApplication qt 消息
- QThread Qt
- Qt自总结(一) QThread
- Qt多线程中调用QTimer