Qt: QTimer和QThread
让QTimer 跑在其他线程. 一般写法如下.
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和QThread的更多相关文章
- 【2017-01-08】QTimer与QThread的调度时间精度
在最近的项目开发中,我发现有的人喜欢用QThread来实现需要循环执行的工作流,而有的人又喜欢用QTimer来实现. 在表面上,两种实现方式似乎都可以,但我觉得QTimer的精度可能会有问题,首先看一 ...
- Qt 线程基础(QThread、QtConcurrent等)
[-] 使用线程 何时使用其他技术替代线程 应该使用 Qt 线程的哪种技术 Qt线程基础 QObject与线程 使用互斥量保护数据的完整 使用事件循环防止数据破坏 处理异步执行 昨晚看Qt的Manua ...
- 在不开启事件循环的线程中使用QTimer(QThread::run函数自带事件循环,在构造函数里创建线程,是一种很有意思的线程用法) good
引入 QTimer是Qt自带的定时器类,QTimer运行时是依赖于事件循环的,简单来说,在一个不开启事件循环(未调用exec() )的线程中,QTimer是无法使用的.通过分析Qt源码可发现,调用QT ...
- Qt 线程基础(QThread、QtConcurrent等) 2
使用线程 基本上有种使用线程的场合: 通过利用处理器的多个核使处理速度更快. 为保持GUI线程或其他高实时性线程的响应,将耗时的操作或阻塞的调用移到其他线程. 何时使用其他技术替代线程 开发人员使用线 ...
- Qt 线程基础(QThread、QtConcurrent、QThreadPool等)
使用线程 基本上有种使用线程的场合: 通过利用处理器的多个核使处理速度更快. 为保持GUI线程或其他高实时性线程的响应,将耗时的操作或阻塞的调用移到其他线程. 何时使用其他技术替代线程 开发人员使 ...
- Qt开发者关于QThread的咆哮——你们都用错了
Qt开发者关于QThread的咆哮——你们都用错了 我们(Qt用户)正广泛地使用IRC来进行交流.我在Freenode网站挂出了#qt标签,用于帮助大家解答问题.我经常看到的一个问题(这让我不厌其烦) ...
- QTimer在QThread环境中失效的问题
QTimer在非QThread的环境下能正常工作.但在QThread环境下,需要做一些改动才能正常工作. 创建Qt的线程有两种方式: 1. 子例化QThread 可以在虚函数run中启动定时器,大致的 ...
- Qt线程(2) QThread中使用WorkObject
一般继承QThread的WorkThread都会在重载的run()中创建临时的WorkObject,这样能确定这个WorkObject在该thread中使用 那如果这个WorkObject是个Sing ...
- pyqt QTimer,QThread例子学习
# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import * from PyQ ...
随机推荐
- 全国各地dns服务器列表
211.103.13.101 江苏省无锡市 移动DNS服务器 211.136.28.231 北京市 移动DNS服务器 211.136.28.234 北京市 移动DNS服务器 211.136.28.23 ...
- SPI通信协议(SPI总线)学习
1.什么是SPI? SPI是串行外设接口(Serial Peripheral Interface)的缩写.是 Motorola 公司推出的一 种同步串行接口技术,是一种高速的,全双工,同步的通信总线. ...
- nvarchar,varchar 区别
char char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值.当你输入的字符大于指定的数时,它会截取超出的字符. nva ...
- opengl中场景变换|2D与3D互转换(转)
opengl中场景变换|2D与3D互转换 我们生活在一个三维的世界——如果要观察一个物体,我们可以: 1.从不同的位置去观察它.(视图变换) 2.移动或者旋转它,当然了,如果它只是计算机里面的物体,我 ...
- [jquery-delegate] iphone_4s _iphone _5c_中不兼容jQuery delegate 事件(does not wok)
1. jQuery .on() and .delegate() doesn't work on iPad http://stackoverflow.com/questions/10165141/jqu ...
- JavaScript中Ajax的使用
AJAX全称为“Asynchronous javascript and XML”(异步javascript和XML),是指一种创建交互式网页应用的网页开发技术.通过在后台与服务器进行少量数据交换,AJ ...
- App主导现在 HTML5领衔未来
HTML5能够让开发人员构建丰富的基于Web应用程序,使其能在任何设备中使用标准的Web浏览器.很多人认为HTML5将会让App过时.到底App还是HTML5会是谁赢得最后的胜利,在业界也有不少讨论, ...
- windows服务器让WEB通过防火墙的问题
服务器环境:windows server 2012 X64WEB服务器:IIS开放8080,PHPSduty开放80 如果关闭防火墙的情况下,不论是IIS还是安装的其他的WEB服务器,都可以正常访问. ...
- keil小技能随用随定义
大家都知道在C语言编程时一般都是先定义再使用这个变量的,不允许在语句的后面再定义,但是有时候我们会在KEIL中发现有些人使用变量就在语句后定义,这时我们自己去尝试却发现总是失败,这是为何呢? 原来是我 ...
- C# GDI绘制仪表盘(纯代码实现)
纯代码实现GDI绘制仪表盘,效果在代码下面. public partial class HalfDashboardUc : UserControl { /// <summary> /// ...