Skip to content
KerwinKoo edited this page Dec 28, 2015 · 4 revisions

Qt 多线程

QThread的常见特性

run

run()是线程的入口,就像main()对于应用程序的作用。

QThread中对run()的默认实现调用了exec(),从而创建一个QEventLoop对象,由其处理该线程事件队列(每一个线程都有一个属于自己的事件队列)中的事件。

简单用代码描述如下:

int QThread::exec()
{
//...
    QEventLoop eventLoop;
    int returnCode = eventLoop.exec();
//...
    return returnCode;
}
  
int QEventLoop::exec(ProcessEventsFlags flags)
{
//...
    while (!d->exit) {
        while (!posted_event_queue_is_empty) {
            process_next_posted_event();
        }
    }
//...
}

由此可见,exec()在其内部不断做着循环遍历事件队列的工作,调用QThreadquit()exit()方法使停止工作,尽量不要使用terminate(),该方法过于粗暴,造成资源不能释放,甚至互斥锁还处于加锁状态。

推荐的使用方式:

#include <QtCore>
class Worker : public QObject
{
    Q_OBJECT
private slots:
    void onTimeout()
    {
        qDebug()<<"Worker::onTimeout get called from?: "<<QThread::currentThreadId();
    }
};
  
#include "main.moc"
  
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug()<<"From main thread: "<<QThread::currentThreadId();
  
    QThread t;
    QTimer timer;
    Worker worker;
  
    QObject::connect(&timer, SIGNAL(timeout()), &worker, SLOT(onTimeout()));
    timer.start(1000);
  
    worker.moveToThread(&t);
  
    t.start();
  
    return a.exec();
}

这是Qt4.7及以后版本推荐的工作方式。

其主要特点就是利用Qt的事件驱动特性,将需要在次线程中处理的业务放在独立的模块(类)中,由主线程创建完该对象后,将其移交给指定的线程,且可以将多个类似的对象移交给同一个线程。

在这个例子中,信号由主线程的QTimer对象发出,之后Qt会将关联的事件放到worker所属线程的事件队列。

由于队列连接的作用,在不同线程间连接信号和槽是很安全的。

引用网址:http://my.oschina.net/u/200628/blog/187865

[[TOC]]

Clone this wiki locally