让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的更多相关文章

  1. 【2017-01-08】QTimer与QThread的调度时间精度

    在最近的项目开发中,我发现有的人喜欢用QThread来实现需要循环执行的工作流,而有的人又喜欢用QTimer来实现. 在表面上,两种实现方式似乎都可以,但我觉得QTimer的精度可能会有问题,首先看一 ...

  2. Qt 线程基础(QThread、QtConcurrent等)

    [-] 使用线程 何时使用其他技术替代线程 应该使用 Qt 线程的哪种技术 Qt线程基础 QObject与线程 使用互斥量保护数据的完整 使用事件循环防止数据破坏 处理异步执行 昨晚看Qt的Manua ...

  3. 在不开启事件循环的线程中使用QTimer(QThread::run函数自带事件循环,在构造函数里创建线程,是一种很有意思的线程用法) good

    引入 QTimer是Qt自带的定时器类,QTimer运行时是依赖于事件循环的,简单来说,在一个不开启事件循环(未调用exec() )的线程中,QTimer是无法使用的.通过分析Qt源码可发现,调用QT ...

  4. Qt 线程基础(QThread、QtConcurrent等) 2

    使用线程 基本上有种使用线程的场合: 通过利用处理器的多个核使处理速度更快. 为保持GUI线程或其他高实时性线程的响应,将耗时的操作或阻塞的调用移到其他线程. 何时使用其他技术替代线程 开发人员使用线 ...

  5. Qt 线程基础(QThread、QtConcurrent、QThreadPool等)

      使用线程 基本上有种使用线程的场合: 通过利用处理器的多个核使处理速度更快. 为保持GUI线程或其他高实时性线程的响应,将耗时的操作或阻塞的调用移到其他线程. 何时使用其他技术替代线程 开发人员使 ...

  6. Qt开发者关于QThread的咆哮——你们都用错了

    Qt开发者关于QThread的咆哮——你们都用错了 我们(Qt用户)正广泛地使用IRC来进行交流.我在Freenode网站挂出了#qt标签,用于帮助大家解答问题.我经常看到的一个问题(这让我不厌其烦) ...

  7. QTimer在QThread环境中失效的问题

    QTimer在非QThread的环境下能正常工作.但在QThread环境下,需要做一些改动才能正常工作. 创建Qt的线程有两种方式: 1. 子例化QThread 可以在虚函数run中启动定时器,大致的 ...

  8. Qt线程(2) QThread中使用WorkObject

    一般继承QThread的WorkThread都会在重载的run()中创建临时的WorkObject,这样能确定这个WorkObject在该thread中使用 那如果这个WorkObject是个Sing ...

  9. pyqt QTimer,QThread例子学习

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import * from PyQ ...

随机推荐

  1. SQL之经典SQL语句大全

    经典SQL语句大全 一.基础 1.说明:创建数据库CREATE DATABASE database-name 2.说明:删除数据库drop database dbname3.说明:备份sql serv ...

  2. java中的类、对象、方法

    类=一个种类(class)东西 对象=属于该种类的一个对象/物件(object,台湾翻译为‘物件’)方法=对这个种类的东西都可以进行的操作 比如我有一辆汽车-类 public class car {. ...

  3. (树的直径)LightOJ -- 1094

    链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=88230#problem/C 求树的直径,这里只不过给每条边增加一个边长属性,变成 ...

  4. yum 常用命令

    yum是一个用于管理rpm包的后台程序,用python写成,可以非常方便的解决rpm的依赖关系.在建立好yum服务器后,yum客户端可以通过 http.ftp方式获得软件包,并使用方便的命令直接管理. ...

  5. string转换成char*

    string 是c++标准库里面其中一个,封装了对字符串的操作 把string转换为char* 有3中方法: 1.data 如: string str="abc"; char *p ...

  6. Android ContentProvider和Uri详解

    一.使用ContentProvider(内容提供者)共享数据 ContentProvider在android中的作用是对外共享数据, 也就是说你可以通过ContentProvider把应用中的数据共享 ...

  7. Ansible配置文件

    官方配置文件文档 Ansible安装完成之后默认配置文件为:/etc/asnible/ansible.cfg Ansible配置文件内容: cat ansible.cfg # config file ...

  8. 集合(二)LinkedList

    上一篇中讲解了ArrayList,本篇文章讲解一下LinkedList的实现. LinkedList是基于链表实现的,所以先讲解一下什么是链表.链表原先是C/C++的概念,是一种线性的存储结构,意思是 ...

  9. 论文笔记(2)-Dropout-Regularization of Neural Networks using DropConnect

    这篇paper使用DropConnect来规则化神经网络.dropconnect和dropout的区别如下图所示.dropout是随机吧隐含层的输出清空,而dropconnect是input unit ...

  10. AndroidPn源码分析(二)

    接上篇: (一)客户端与服务器建立连接 上一篇写到ClientSession createClientSession这里,创建一个客户端的session.在SessionManager类中创建了ses ...