QT学习笔记5

QT可以多线程处理任务。这一节是多线程的基础。


进程和线程

关于进程和线程之间关系最经典的说法是:进程是资源分配的最小单位,线程是系统调度的最小单位。

Since threads use the same address space, it is easier and faster for threads to exchange data than it is for processes. Data does not have to be serialized and copied. While IPC is used in communication of processes.

用python实现一下多线程例子如下:

#!/usr/bin/python
# python thread.py
# python -m gevent.monkey thread.py
import threading
class Thread(threading.Thread):
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name
   
    def run(self):
        for i in xrange(10):
            print self.name
threadA = Thread("A")
threadB = Thread("B")
threadA.start()
threadB.start()

在windows下会打印 ABBABBBBBABABABAAAAA,可见两个线程不是均匀切换,这和操作系统策略有关。

那么QT在什么情况下用到多线程?

1.Make processing faster by making use of multicore processors.

2.Keep the GUI thread or other time critical threads responsive by offloading long lasting processing or blocking calls to other threads.

第一个是因地制宜使用多核,第二个是任务分流达到负载均衡。


简单的时钟

现在用一个线程在QWidget文本控件中显示时间。

工作线程每10毫秒获取一下时间,使用QDateTime类的静态方法currentDateTime()。如果时间改变,则新的时间被获取进行显示。

这个例子主要是展示工作进程发送信号到GUI进程。我们只需要添加一个信号到QThread,然后用signal/slot机制连接到主线程中。

//.h
#ifndef CLOCKTHREAD_H
#define CLOCKTHREAD_H

#include <QWidget>
#include <QThread>

class ClockThread : public QThread
{
    Q_OBJECT
signals:
    void sendTime(QString time);
private:
    void run();
    QString m_lastTime;
private slots:
    void timerHit();
};

#endif

工作线程ClockThread继承自QThread线程,自己定义了一个信号(以前的程序只定义槽)和一个槽。

//.cpp
#include "clockthread.h"
#include "ui_clockthread.h"
#include <QTimer>
#include <QString>
#include <QDateTime>

void ClockThread::run()
{
    QTimer timer;
    connect(&timer,SIGNAL(timeout()),this,SLOT(timerHit()), \
    Qt::DirectConnection);
    timer.setInterval(10);
    timer.start();
    exec();
    timer.stop();
}

void ClockThread::timerHit()
{
    QString newTime= QDateTime::currentDateTime().toString  \
    ("ddd MMMM d yy, hh:mm:ss");
    if(m_lastTime!=newTime)
    {
        m_lastTime=newTime;
        emit sendTime(newTime);
    }
}

实现工作线程的成员函数

//main
#include "clockthread.h"
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget widget;
    QLabel *label=new QLabel;
    ClockThread w;
    QHBoxLayout *layout=new QHBoxLayout(&widget);
    layout->addWidget(label);
    widget.setWindowTitle("Clock");

    ClockThread clockThread;
    QObject::connect(&clockThread,SIGNAL(sendTime(QString)),label,   \
    SLOT(setText(QString)),Qt::QueuedConnection);
    clockThread.start();
    widget.show();
    app.exec();
    clockThread.quit();
    clockThread.wait();

    return 0;
}

整个的工作逻辑是:

在ClockThread::run()中new一个timer,设定计时值10ms。当timer溢出时产生一个信号给timerHit。

在ClockThread::timerHit()中判断是否是新的时间,然后发送信号sendTime。这个sendTime方法不需要实现,它携带newTime变量作为信号连接到主线程的槽setText上显示时间。

运行结果如下:

图片


Reference

[1].http://qt-project.org/doc/qt-4.8/thread-basics.html



Previous     Next
/
Published under (CC) BY-NC-SA in categories C&&C++  tagged with