在QThread中使用QTimer

设计界面原型用定时器模拟程序运行,处理数据的程序运行时间很长,并要实时显示进度,需要使用多线程技术。运行程序出现下面的警告:

1

QObject::startTimer: timers cannot be started from another thread

警告无法再另一个进程中开始定时器。在QTimer的官方文档里,有下面一段话:

1

In multithreaded applications, you can use <a href="http://qt-project.org/doc/qt-4.8/qtimer.html">QTimer</a> in any thread that has an event loop. To start an event loop from a non-GUI thread, use <a href="http://qt-project.org/doc/qt-4.8/qthread.html#exec">QThread::exec</a>(). Qt uses the timer‘s <a href="http://qt-project.org/doc/qt-4.8/qobject.html#thread">thread affinity</a> to determine which thread will emit the <a href="http://qt-project.org/doc/qt-4.8/qtimer.html#timeout">timeout()</a> signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.

指出必须在同一个线程里开始和停止定时器,也就是只有在创建定时器的线程里才能接受到timeout()信号。我的代码中使用QObject::moveToThread()方法实现多线程

1

2

3

4

5

6

7

8

work_thread = new QThread();

local_dir_data_importer_service = new LocalDirDataImporterService(); //TODO:? parent

local_dir_data_importer_service->setImportDataModel(import_model);

local_dir_data_importer_service->moveToThread(work_thread);

work_thread->start();

connect(work_thread,SIGNAL(started()),local_dir_data_importer_service,SLOT(excuteImport()));

在LocalDirDataImporterService构造函数中初始化定时器

1

2

3

4

5

6

7

LocalDirDataImporterService::LocalDirDataImporterService(QObject *parent) :

//...

{ //...

list_timer = new QTimer();

} //...

在LocalDirDataImporterService::excuteImport()中开启定时器

1

2

3

4

5

6

7

8

void LocalDirDataImporterService::excuteImport()

{

list_timer->setInterval(1000);

list_timer->start();

this->connect(list_timer,SIGNAL(timeout()),this,SLOT(testImportItem()));

}

如上,定时器在GUI进程中初始化,无法在子工作进程中开始定时器。需要在子工作进程中初始化定时器。

1

2

3

4

5

6

7

8

9

void LocalDirDataImporterService::excuteImport()

{

list_timer = new QTimer();

list_timer->setInterval(1000);

list_timer->start();

this->connect(list_timer,SIGNAL(timeout()),this,SLOT(testImportItem()));

}

这样定时器就可以正常使用了。



Stackoverflow上看到另一种方法,将定时器和工作类都移到某个子进程:
http://stackoverflow.com/questions/15835267/qthread-and-qtimer

工作类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

class Worker : public QObject

{

Q_OBJECT

public:

explicit Worker(QObject *parent = 0) : QObject(parent) {}

signals:

void doSomething();

public slots:

void trigger() {

emit doSomething();

}

};

主程序

C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

MainThreadObject o;

QThread *thread = new QThread;

Worker w;

QTimer timer;

timer.setInterval(1000);

timer.moveToThread(thread);

w.moveToThread(thread);

QObject::connect(thread, SIGNAL(started()), &timer, SLOT(start()));

QObject::connect(&w, SIGNAL(doSomething()), &o, SLOT(doSomething()));

QObject::connect(&timer, SIGNAL(timeout()), &w, SLOT(trigger()));

thread->start();

return a.exec();

}

时间: 2024-12-28 11:55:02

在QThread中使用QTimer的相关文章

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

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

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)

QThread中的互斥、读写锁、信号量、条件变量

该文出自:http://www.civilnet.cn/bbs/browse.php?topicno=78431 在gemfield的<从pthread到QThread>一文中我们了解了线程的基本使用,但是有一大部分的内容当时说要放到这片文章里讨论,那就是线程的同步问题.关于这个问题,gemfield在<从进 程到线程>中有一个比喻,有必要重新放在下面温习下: ******************************* 最后用一个比喻来总结下: 1.一个进程就好比一个房子里有一

pyqt4:在Qthread中使用定时器Qtimer注意

GUI main 部分,Work2是线程类 timer 调用线程类中的一个方法 实例化线程 self.s2_thread=Worker2() 定时器绑定要做的事情以及这个事情需要多长时间触发 self.log_get=QtCore.QTimer() self.log_get.singleShot(30000,self.s2_thread.get_mem_error_logfile_content) self.log_get.singleShot(90000,self.s2_thread.get_

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(o

解析Qt中QThread使用方法

本文讲述的是在Qt中QThread使用方法,QThread似乎是很难的一个东西,特别是信号和槽,有非常多的人(尽管使用者本人往往不知道)在用不恰当(甚至错误)的方式在使用QThread,随便用google一搜,就能搜出大量结果出来.无怪乎Qt的开发人员 Bradley T. Hughes 声嘶力竭地喊you are-doing-it-wrong 和众多用户一样,初次看到这个时,感到 Bradley T. Hughes有 些莫名奇妙,小题大作.尽管不舒服,当时还是整理过一篇博客QThread 的使

怎样正确的使用QThread类

背景描述: 以前,继承 QThread 重新实现 run() 函数是使用 QThread唯一推荐的使用方法.这是相当直观和易于使用的.但是在工作线程中使用槽机制和Qt事件循环时,一些用户使用错了.Qt  核心开发人员Bradley T. Hughes, 推荐使用QObject::moveToThread 把它们移动到线程中.不幸的是, 以用户反对这样使用.Olivier Goffart, 前Qt  核心开发人之一, 告诉这些用户你们不这样做就错了.最终这俩种用法我们都在QThread的文档中发现

qt QThread

QThread类提供了一个平台无关的方式来管理线程. 一个QThread对象在程序控制中管理一个线程.线程在run()中开始执行.默认情况下,run()通过调用exec()启动事件循环并在线程里运行一个Qt的事件循环. 可以使用worker-object通过QObject::moveToThread将它们移动到线程.class Worker : public QObject { Q_OBJECT public slots: void doWork(const QString &parameter

重点:怎样正确的使用QThread类(注:包括推荐使用QThread线程的新方法QObject::moveToThread)

背景描述: 以前,继承 QThread 重新实现 run() 函数是使用 QThread唯一推荐的使用方法.这是相当直观和易于使用的.但是在工作线程中使用槽机制和Qt事件循环时,一些用户使用错了.Qt  核心开发人员Bradley T. Hughes, 推荐使用QObject::moveToThread 把它们移动到线程中.不幸的是, 以用户反对这样使用.Olivier Goffart, 前Qt  核心开发人之一, 告诉这些用户你们不这样做就错了.最终这俩种用法我们都在QThread的文档中发现