在QThread中使用QTimer

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

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

指出必须在同一个线程里开始和停止定时器,也就是只有在创建定时器的线程里才能接受到timeout()信号。我的代码中使用QObject::moveToThread()方法实现多线程
[cpp]
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()));
[/cpp]
在LocalDirDataImporterService构造函数中初始化定时器
[cpp]
LocalDirDataImporterService::LocalDirDataImporterService(QObject *parent) :
//…
{ //…
list_timer = new QTimer();
} //…
[/cpp]
在LocalDirDataImporterService::excuteImport()中开启定时器
[cpp]
void LocalDirDataImporterService::excuteImport()
{
list_timer->setInterval(1000);
list_timer->start();
this->connect(list_timer,SIGNAL(timeout()),this,SLOT(testImportItem()));
}
[/cpp]
如上,定时器在GUI进程中初始化,无法在子工作进程中开始定时器。需要在子工作进程中初始化定时器。
[cpp highlight=”3″]
void LocalDirDataImporterService::excuteImport()
{
list_timer = new QTimer();
list_timer->setInterval(1000);
list_timer->start();
this->connect(list_timer,SIGNAL(timeout()),this,SLOT(testImportItem()));
}
[/cpp]
这样定时器就可以正常使用了。

Stackoverflow上看到另一种方法,将定时器和工作类都移到某个子进程:
<//stackoverflow.com/questions/15835267/qthread-and-qtimer>
工作类
[cpp]
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0) : QObject(parent) {}
signals:
void doSomething();
public slots:
void trigger() {
emit doSomething();
}
};
[/cpp]
主程序
[cpp]
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();
}
[/cpp]