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(){}
};

  

看起来和平时用的一模一样.  →_→

时间: 2024-11-08 09:24:06

Qt: QTimer和QThread的相关文章

pyqt QTimer,QThread例子学习

# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import * from PyQt4.Qt import * from PyQt4.QtCore import * from start import Ui_Form import sys class Example(QDialog,Ui_Form): def __init__(self,parent=None): super(E

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

使用线程 基本上有种使用线程的场合: 通过利用处理器的多个核使处理速度更快. 为保持GUI线程或其他高实时性线程的响应,将耗时的操作或阻塞的调用移到其他线程. 何时使用其他技术替代线程 开发人员使用线程时需要非常小心.启动线程是很容易的,但确保所有共享数据保持一致很难.遇到问题往往很难解决,这是由于在一段时间内它可能只出现一次或只在特定的硬件配置下出现.在创建线程来解决某些问题之前,应该考虑一些替代的技术 : 替代技术 注解 QEventLoop::processEvents() 在一个耗时的计

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

引入 QTimer是Qt自带的定时器类,QTimer运行时是依赖于事件循环的,简单来说,在一个不开启事件循环(未调用exec() )的线程中,QTimer是无法使用的.通过分析Qt源码可发现,调用QTimer::start()后仅仅是在系统的定时器向量表中添加了一个定时器对象,但定时器并没有真正开启.定时器的开启需要通过processEvent()开始的一系列调用后才会真正得开启,这个过程中会处理定时器向量表中所有的定时器对象.那么实际exec()中也是在不断地调用processEvent()方

[Qt学习篇]Qthread实现多线程操作

一.QThread类概述 QThread类为用户管理多线程提供了一种平台无关的途径. #include <QThread> 继承自QObject类 二.QThread类详述 QThread对象在程序内部进行控制线程的管理,QThread起始于run()函数额执行.默认情况下,run()通过调用exec()启动事件循环(event loop),并在线程内部执行Qt 的事件循环. 以下示例通过QObject::moveToThread()调用把worker对象添加到线程中运行: class Wor

Qt线程(2) QThread中使用WorkObject

一般继承QThread的WorkThread都会在重载的run()中创建临时的WorkObject,这样能确定这个WorkObject在该thread中使用 那如果这个WorkObject是个Singleton是种什么情况呢? 方式2:在QThread中使用WorkObject 1.创建WorkObject 1 #include <QObject> 2 #include <QDebug> 3 #include <QThread> 4 5 #define DEBUG(x)

Qt QThread必须要了解的几个函数

概述 如果想对Qt中的QThread有个更加深刻的了解,必须要知道这几个重要的函数,现在就一一介绍下. 函数介绍 属性 返回值 函数体 功能 static QThread * QThread::currentThread() 返回当前线程的指针,静态函数. static Qt::HANDLE QThread::currentThreadId() 返回当前线程的句柄,静态函数 static bool QThread::isFinished() const 如果线程执行结束,返回true,否则返回f

Qt同步线程(比较清楚,而且QMutex QMutexLocker QReadWriteLock QSemaphore QWaitCondition 每个都有例子)

Qt同步线程 我们知道,多线程有的时候是很有用的,但是在访问一些公共的资源或者数据时,需要进行同步,否则会使数据遭到破坏或者获取的值不正确.Qt提供了一些类来实现线程的同步,如QMutex,QMutexLocker,QReadWriteLock,QReadLocker,QWriteLocker,QSemaphore和QWaitCondition.下面我们分别来看它们的用法: QMutex 首先,简单的了解一下QMutex提供的函数. 构造函数:QMutex ( RecursionMode mod

Qt 线程基础

(转自:http://my.oschina.net/laopiao/blog/88158) 保谓线程? 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据结算的时候,在相同的桌面上可能有一个播放器正在播放你最喜欢的歌曲.这是一个两个进程并行工作的例子:一个进程运行电子表格程序;另一个进程运行一个媒体播放器.这种情况最适合用多任务这个词来描述.进一步观察媒体播放器,你会发现在这个进程内,又存在并行的工作.当媒体播放器向音频驱动发送音乐数据的时候,用户界

[Qt总结篇]终端远程升级客户端

环境: QT4.8.5 for Windows(Qt Creator+MinGW) 一.写在前面: 1.深度:鉴于C/C++的功底还远远不足,个人主要精力还是学习C/C++,所以没打算继续深入研究Qt. 2.Why Qt:之前没做过界面相关的东西,也一直很好奇,那么炫的界面怎么做出来的.现在需要一个界面,也没人要求必须用微软的MFC,鉴于都要现学现用(也没人可以请教),而手边有一本半年前买的<C++ GUI QT4编程>(翻过前两章),于是决定上Qt. 3.内容:不涉及具体编码,在必要时会用代