官术网_书友最值得收藏!

1.2 多線程的創建和管理

Qt通過3種形式提供對線程的支持,分別是平臺無關的線程類、線程安全的事件投遞、跨線程的信號槽連接。

Qt中主要的線程類如下。

QThread:提供跨平臺的多線程解決方案。

QThreadStorage:提供逐線程數據存儲。

QMutex:提供相互排斥的鎖或互斥量。

QMutexLocker:輔助類,可自動對 QMutex 加鎖與解鎖。

QReadWriteLock:提供可以同時讀寫操作的鎖。

QReadLocker與QWriteLocker:自動對QReadWriteLock 加鎖與解鎖。

QSemaphore:提供整型信號量,是互斥量的泛化。

QWaitCondition:線程在被其他線程喚醒之前一直休眠。

QThread是Qt線程中的一個公共的抽象類,所有的線程類都是從QThread抽象類中派生的。需要實現QThread中的虛函數run,可通過start函數來調用run函數。在默認情況下,QThread::run會啟動一個事件循環(QEventLoop::exec)。線程相關的函數如下。

void run:線程體函數,用于定義線程的功能。

void start:啟動函數,用于將線程入口地址設置為run函數。

void terminate:用于強制結束線程,不保證數據完整性和資源釋放。

QCoreApplication::exec總是在主線程(執行main的線程)中被調用,不能從一個QThread中調用。在圖形用戶界面(GUI)程序中,主線程也稱為GUI線程,是唯一允許執行GUI相關操作的線程。另外,必須在創建一個QThread前創建QApplication(或QCoreApplication)對象。

當線程啟動和結束時,QThread會發送信號started和finished,可以使用isFinished和isRunning來查詢線程的狀態。

通過靜態函數currentThreadId和currentThread返回當前正在執行的線程的標識,前者返回線程的ID,后者返回一個線程指針。

如果要設置線程的名稱,可以在啟動線程之前調用setObjectName。如果不調用setObjectName函數,那么線程的名稱將是線程對象的運行時類型(QThread子類的類名)。

在新的線程中使用QThread類執行代碼可通過以下幾種方式。

1.繼承QThread類

重寫QThread的void run函數,在重寫的函數中添加需要執行的代碼。在以下代碼中,NewThread類通過繼承QThread類,重寫run函數,實現一個新的線程。

  #include <QThread>
class NewThread : public QThread
{
public:
explicit NewThread(QObject *parent = 0);
protected:
void run()
{
// 具體語句
}

2.使用 QThread::create

使用 QThread::create(要求Qt版本至少為Qt 5.10)直接創建一個QThread對象,它可接收一個函數類型的參數,當調用QThread::start時會在新的線程中執行此函數。以下代碼為使用QThread::create函數的示例。

  void function()
{
//具體語句
}
QThread *new_thread = QThread::create(function);
new_thread->start();

3.直接創建一個QThread對象

直接創建一個QThread對象,將一個QObject對象移動到此線程,則使用QMetaObject :: invokeMethod調用此對象的槽函數就會在新的線程中執行。以下代碼為使用moveToThread的示例。

  class Object : public QObject
{
Q_OBJECT
public:
explicit Object(QObject *parent = nullptr);
public slots:
void function() {
//具體語句
}
};
QThread *new_thread = new QThread();
Object *object = new Object();
object->moveToThread(new_thread);//將對象交給線程
new_thread->start();
QMetaObject::invokeMethod(object, "function");

QRunnable類可以和QThreadPool(線程池)配合使用。和QThread的第一種使用方法類似,開發者也需要通過繼承并重寫QRunnable::run函數,從而在新的線程中執行代碼。以下代碼為使用QRunnable的示例。

  class Runnable : public QRunnable
{
public:
void run() override
{
//具體語句
}
};
QRunnable *runnable = new Runnable();
runnable->setAutoDelete(runnable);
QThreadPool::globalInstance()->start(runnable);

QtConcurrent類是基于QRunnable封裝的上層接口,可以很方便地在一個新的線程中執行一個函數,也可以和QThreadPool配合使用,以滿足更靈活的功能需求。以下代碼為使用QtConcurrent的示例。

  void function()
{
//具體語句
}
QtConcurrent::run(function);
主站蜘蛛池模板: 方城县| 延寿县| 揭东县| 河曲县| 万安县| 九江市| 波密县| 太仓市| 景泰县| 六盘水市| 长宁区| 鲁山县| 娄烦县| 正宁县| 乌兰浩特市| 阳原县| 屏边| 建宁县| 综艺| 德兴市| 大理市| 桂林市| 碌曲县| 天柱县| 潍坊市| 绩溪县| 青浦区| 松江区| 常宁市| 福安市| 克什克腾旗| 莱阳市| 师宗县| 乌拉特前旗| 康马县| 盐山县| 云南省| 新巴尔虎左旗| 轮台县| 沙河市| 昭觉县|