一個進程(Process)是一個包括有自身執行位址的程式,在一個多工的作業系統中,可以分配CPU時間給每一個進程,CPU在片段時間中執行某個進程,然後下一個時間片段跳至另一個進程去執行,由於轉換速度很快,這使得每個程式像是在同時進行處理一般。
一個執行緒是進程中的一個執行流程,一個進程中可以同時包括多個執行緒,也就是說一個程式中同時可能進行多個不同的子流程,這使得一個程式可以像是同時間
處理多個事務,例如一方面接受網路上的資料,另一方面同時計算資料並顯示結果,一個多執行緒程式可以同時間處理多個子流程。
在Qt中,有許多類別,其本身在一些操作上即設計為非同步,透過Signal與Slot,可以讓您不用了解多執行緒,也可以實現非阻斷的操作,但某些時候,您仍必須親自實作多執行緒功能。
在Qt中要實現執行緒功能,可以繼承QThread類別,並重新定義run()方法,之後要啟動一個執行緒,則建構這個自訂的物件,並執行start()方法。
下面這個程式是個簡單的程式,您可以看到如何繼承QThread、重新定義run()方法及如何啟動執行緒,程式中將以兩個執行緒「同時」對一個QPixmap畫圓,顯示兩個「同時」進行的流程:
#ifndef CIRCLETHREAD_H #define CIRCLETHREAD_H
#include <QThread>
class QLabel; class QPixmap;
class CircleThread : public QThread { Q_OBJECT public: CircleThread(QLabel *label, QPixmap *pixmap, int y); protected: void run(); private: QLabel *label; QPixmap *pixmap; int y; };
#endif
CircleThread建構函式中,QPixmap是QLabel將顯示的圖片,而y值是畫圓時的位置,CircleThread實作如下:
#include "CircleThread.h" #include <QPainter> #include <QLabel> #include <QPixmap>
CircleThread::CircleThread(QLabel *label, QPixmap *pixmap, int y) { this->label = label; this->pixmap = pixmap; this->y = y; }
void CircleThread::run() { QPainter painter(pixmap); for(int i = 10; i < 300; i += 10) { painter.drawEllipse(i, y, 30, 30); label->setPixmap(*pixmap); QThread::msleep(500); } }
在run()方法中,將在QPixmap上建構QPainter,然後依序畫10個圓,接著將畫好的QPixmap再次設置給
QLabel,以重新在QLabel上顯示新的繪製畫面。QThread::msleep()可以令目前的執行緒暫停所設置的毫秒數。您可以撰寫以下的程
式來使用CircleThread:
#include <QApplication> #include <QLabel> #include "CircleThread.h"
int main(int argc, char *argv[]) { QApplication app(argc, argv);
QLabel *label = new QLabel; label->resize(320, 200);
QPixmap pixmap(320, 200); pixmap.fill(Qt::white); CircleThread *thread1 = new CircleThread(label, &pixmap, 50); CircleThread *thread2 = new CircleThread(label, &pixmap, 100); label->setWindowTitle("Thread Demo"); label->show(); thread1->start(); thread2->start(); return app.exec(); }
啟動執行緒是使用start()方法,下圖為執行時的參考畫面,您可以看到一個視窗,兩個圓在「同時」繪製,雖說是同時,其實也只是錯覺而已,其實是CPU往來兩個流程之間不斷的進行繪製圓的動作而已。:

|
|