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 ...
随机推荐
- Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.liuyang.JDbCTemplate.PersonDao]: No default constructor fo
错误是说我的配置文件中没有对构造函数进行配置,所以找不到构造函数,在配置文件application.xml中加入如下句子: <bean id="personDao" clas ...
- 大文件webuploader的基本使用
webuploader的简单使用 需要的文件 自备 百度很多 webuploader.js uploader.swf jQuery <!DOCTYPE html> <htm ...
- C - 无间道之并查集 HihoCoder - 1066
输入 每个测试点(输入文件)有且仅有一组测试数据. 每组测试数据的第1行为一个整数N,表示黑叔叔总共进行的操作次数. 每组测试数据的第2~N+1行,每行分别描述黑叔叔的一次操作,其中第i+1行为一个整 ...
- java实现自动生成四则运算
Github项目链接:https://github.com/shoulder01/Fouroperation.git 一.项目相关要求 1. 使用 -n 参数控制生成题目的个数(实现) 2.使用 -r ...
- SSH中设置字符编码防止乱码
1.在web.xml中加入一个过滤器和过滤范围的配置 <filter><filter-name>encoding</filter-name><filter-c ...
- ORACLE EBS xml publisher 报表输出字符字段前部"0"被EXCEL自动去掉问题
http://www.cnblogs.com/lzsu1989/archive/2012/10/17/2728528.html Oracle EBS 提供多种报表的开发和输出形式,由于MS Ex ...
- Windows 7下通过Excel2007连接Oracle数据库并对表查询
http://blog.csdn.net/pan_tian/article/details/8133668 1. 环境变量的设置 1.1 ORACLE_HOME环境变量的设置,我这里指向了我的Ora ...
- SQL SERVER存储过程中使用事务与捕获异常
https://www.douban.com/note/559596669/ 格式类似于 CREATE PROCEDURE YourProcedure ASBEGIN SET NOCOUNT O ...
- 配置Jenkins构建失败触发邮件报警机制
系统管理 1.进入系统管理-->系统设置 定位到Jenkins Location配置项 配置系统管理员邮件地址 系统管理员邮件地址需要同发送报警邮件地址相同 定位到邮件通知 配置SMTP ...
- .NET Core 和 .NET .Framework 速度比较
废话不多说! 一下是 .NET core 和 .NET framework 速度对比. 两者使用最慢的冒泡排序算法: 排序10万条数据 次数 .NET CORE(耗时) .NET framework ...