深圳龍崗區(qū)寶龍街道正規(guī)seo多少錢
QThread
- QThread類
- 枚舉類型
- 成員函數(shù)
- 可重寫函數(shù)
- 公共槽
- 信號
- 靜態(tài)成員函數(shù)
- 保護(hù)函數(shù)
- 靜態(tài)保護(hù)函數(shù)
- QThread簡單案例1
- QThread簡單案例2
QThread類
標(biāo)準(zhǔn)頭文件:#include <QThread>
qmake: QT += core
繼承(父): QObject
枚舉類型
線程的優(yōu)先級
enum Priority { IdlePriority, LowestPriority, LowPriority, NormalPriority, HighPriority, …, InheritPriority }
{ 空閑優(yōu)先級,最低優(yōu)先級,低優(yōu)先級,正常優(yōu)先級,高優(yōu)先級,…,繼承優(yōu)先級 }
此枚舉類型指示操作系統(tǒng)應(yīng)該如何調(diào)度新創(chuàng)建的線程。
常數(shù) | 價(jià)值 | 描述 |
---|---|---|
QThread::IdlePriority | 0 | 僅在沒有其他線程運(yùn)行時調(diào)度。 |
QThread::LowestPriority | 1 | 調(diào)度頻率低于低優(yōu)先級。 |
QThread::LowPriority | 2 | 計(jì)劃頻率低于正常優(yōu)先級。 |
QThread::NormalPriority | 3 | 操作系統(tǒng)的默認(rèn)優(yōu)先級。 |
QThread::HighPriority | 4 | 比正常優(yōu)先級計(jì)劃得更頻繁。 |
QThread::HighestPriority | 5 | 比高優(yōu)先級計(jì)劃得更頻繁。 |
QThread::TimeCriticalPriority | 6 | 盡可能經(jīng)常安排。 |
QThread::InheritPriority | 7 | 使用與創(chuàng)建線程相同的優(yōu)先級。這是默認(rèn)值。 |
成員函數(shù)
類型 | 方法 | 說明 |
---|---|---|
構(gòu)造函數(shù) | QThread(QObject *parent = nullptr) | 參數(shù)父類QObject指針 |
virtual | ~QThread() | 虛析構(gòu)函數(shù),當(dāng)基類指針指向子類時,使用delete時,會先調(diào)用子類析構(gòu)函數(shù),在調(diào)用父類構(gòu)造函數(shù),釋放資源。 |
QAbstractEventDispatcher * | eventDispatcher() const | |
void | exit(int returnCode = 0) | |
bool | isFinished() const | |
bool | isInterruptionRequested() const | |
bool | isRunning() const | |
int | loopLevel() const | |
QThread::Priority | priority() const | |
void | requestInterruption() | |
void | setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) | |
void | setPriority(QThread::Priority priority) | |
void | setStackSize(uint stackSize) | |
uint | stackSize() const | |
bool | wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever)) | 阻塞線程,直到滿足以下任一條件,這提供了與POSIX pthread_join()函數(shù)相似的功能。 |
bool | wait(unsigned long time) |
可重寫函數(shù)
virtual bool event(QEvent *event) override
公共槽
何為公共槽函數(shù),就是可以被子類直接調(diào)用
void quit()
void start(QThread::Priority priority = InheritPriority)
void terminate()
信號
void finished()
void started()
靜態(tài)成員函數(shù)
QThread * create(Function &&f, Args &&... args)
QThread * create(Function &&f)
QThread * currentThread()
Qt::HANDLE currentThreadId()
int idealThreadCount()
void msleep(unsigned long msecs)
void sleep(unsigned long secs)
void usleep(unsigned long usecs) //強(qiáng)制當(dāng)前線程休眠微秒。
//[將當(dāng)前線程的執(zhí)行讓給另一個可運(yùn)行線程(如果有)。請注意,操作系統(tǒng)決定切換到哪個線程。]
void yieldCurrentThread()
保護(hù)函數(shù)
int exec()
virtual void run()
靜態(tài)保護(hù)函數(shù)
基于enabled參數(shù)啟用或禁用當(dāng)前線程的終止。線程必須是由QThread啟動的。
void setTerminationEnabled(bool enabled = true)
QThread簡單案例1
官方的例子,值得信賴
例如:Worker 是我們創(chuàng)建的一個子線程。
繼承QObject的優(yōu)點(diǎn):內(nèi)存回收安全,支持信號與槽。
例如:Controller 是主線程。
共同點(diǎn):他們都繼承自QObject
代碼里面的connect的這種寫法我比較推薦,參數(shù)怎么變都不影響,減少修改次數(shù)
這種線程的特點(diǎn):任務(wù)線程里面的每個槽函數(shù)都是一個事件循環(huán),即你可以處理耗時操作,讀寫文件,數(shù)據(jù)計(jì)算,大量循環(huán)等等(目前我我是使用這種方法,還不錯)。
class Worker : public QObject
{Q_OBJECTpublic slots:void doWork(const QString ¶meter) {QString result;/* ... 處理大數(shù)據(jù) ... */emit resultReady(result); //處理完數(shù)據(jù),發(fā)到主線程顯示}signals:void resultReady(const QString &result);
};class Controller : public QObject
{Q_OBJECTQThread workerThread;//線程棧 自動銷毀,推薦使用
public:Controller() {Worker *worker = new Worker; //創(chuàng)建任務(wù)子線程worker->moveToThread(&workerThread); //添加到線程,實(shí)際應(yīng)該可以添加多個任務(wù)子線程。connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);//線程完成這個任務(wù),就將這個任務(wù)線程對象刪除connect(this, &Controller::operate, worker, &Worker::doWork);//發(fā)射信號,通知任務(wù)線程做事。connect(worker, &Worker::resultReady, this, &Controller::handleResults);//接收任務(wù)子線程處理好的數(shù)據(jù)workerThread.start(); //正式開啟線程,}~Controller() {workerThread.quit(); //先退出沒處理的任務(wù)workerThread.wait(); //已經(jīng)在處理的任務(wù),等待處理完,在退出}
public slots:void handleResults(const QString &);
signals:void operate(const QString &);
};
任務(wù)插槽中的代碼將在一個單獨(dú)的線程中執(zhí)行。但是,您可以自由地將任務(wù)線程的插槽連接到來自任何對象、任何線程的任何信號。由于一種稱為排隊(duì)連接的機(jī)制,
跨不同線程連接信號和插槽是安全的
。
QThread簡單案例2
讓代碼在單獨(dú)的線程中運(yùn)行的另一種方法是子類化QThread并重新實(shí)現(xiàn)run()。這種使用的場景一般是不需要和主線程交互,比如只完成文件寫操作等等。
例如:
//任務(wù)線程
class WorkerThread : public QThread
{Q_OBJECTvoid run() override {QString result;/* ... here is the expensive or blocking operation ... */emit resultReady(result);}
signals:void resultReady(const QString &s);
};
//主線程 分配任務(wù)
void MyObject::startWorkInAThread()
{WorkerThread *workerThread = new WorkerThread(this);//傳入this,就是QObject的指針,資源的釋放,即是線程的構(gòu)造函數(shù)傳參。connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);workerThread->start();//開啟run()方法
}
在該示例中,線程將在
run
函數(shù)返回后退出。除非調(diào)用exec()
,否則線程中不會運(yùn)行任何事件循環(huán)(即做完這件事,就不再執(zhí)行事件循環(huán)了)。
重要的是要記住,QThread實(shí)例存在于實(shí)例化它的舊線程中,而不是存在于調(diào)用run()的新線程中。這意味著所有QThread的隊(duì)列槽和調(diào)用的方法都將在舊線程中執(zhí)行。因此,希望在新線程中調(diào)用槽的開發(fā)人員必須使用工作對象方法;新插槽不應(yīng)該直接在子類化的QThread中實(shí)現(xiàn)。
與排隊(duì)槽或調(diào)用的方法不同,直接在QThread對象上調(diào)用的方法將在調(diào)用該方法的線程中執(zhí)行。當(dāng)子類化QThread時,請記住構(gòu)造函數(shù)在舊線程中執(zhí)行(主線程id一致),而run()在新線程中執(zhí)行(線程id新的)。如果一個成員變量是從兩個函數(shù)中訪問的,那么這個變量是從兩個不同的線程中訪問的。檢查這樣做是否安全。
注意:在跨不同線程與對象交互時必須小心。一般來說,函數(shù)只能從創(chuàng)建QThread對象本身的線程中調(diào)用(例如setPriority()),除非文檔中另有說明。